目录

Android开发笔记

Android5.0常用颜色属性说明

在使用Eclipse的时代,我们很少去在style文件给整个应用或者Activity去设定颜色,那是因为即使设置也不会提升用户的视觉效果。但是材料设计号称让没有设计功底的人也能做出漂亮的App,那我们今天就来看看在Androi5.0中常用的颜色属性。

我们可以先定义一个style,然后在这个style中设定每一个Activity或者整个App的颜色,最后在清单文件中来给某个Activity设置主题即可。代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<style name="AppTheme.NoActionBar">
    <!--状态栏颜色-->
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <!--控制各个控件被选中时的颜色-->
    <item name="colorAccent">@color/colorAccent</item>
    <!--页面背景色-->
    <item name="android:windowBackground">@color/windowBackg</item>
    <!--底部导航栏颜色-->
    <item name="android:navigationBarColor">@color/navigationColor</item>
    <!--Appbar背景色-->
    <item name="android:colorPrimary">@color/colorPrimary</item>
    <!--ToolBar上的Title颜色-->
    <item name="android:textColorPrimary">@color/textColorPrimary</item>
    <!--各个控制控件的默认颜色-->
    <item name="android:colorControlNormal">@color/colorControlNormal</	item>
</style>

最后再来一张图详细说明每个item设定的到底是哪里的颜色: ./1.png

ConstraintLayout基本使用之toLeftOf 、toTopOf、toRightOf、toBottomOf

关于ConstraintLayout的博客、文章想必大家已经见过很多了,都是很全面的,今天这篇博客主要将ConstraintLayout的

1
2
3
4
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintTop_toTopOf
...

以上到底怎么理解呢?下面我将通过图片+文字来解释。

现在假设屏幕中间有个长宽为100dp的红色正方形,屏幕左上方有个宽高为50dp的黑色正方形,如下: 接下来我们一个一个试试这些参数吧!

1、layout_constraintLeft_toLeftOf(可以看出黑色正方形左边和红色正方形左边对齐)

./2.png

2、layout_constraintLeft_toRightOf(黑色正方形的左边和红色正方形的右边对齐)

./3.png

3、layout_constraintRight_toLeftOf(黑右对齐红左)

./4.png

4、layout_constraintRight_toRightOf(黑右对齐红右)

./5.png

剩余四个:

1
2
3
4
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf

也是同理。

让我们看一下这个参数的统一命名:layout_constraintA_toBOf,

也即代表当前布局的A方向,对齐目标布局的B方向

Android 沉浸式标题栏设置,顶部view到状态栏

Android 沉浸式标题栏设置,顶部view到状态栏

布局xml文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<TextView
        android:id="@+id/tv_top_bg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:maxHeight="140dp"
        android:background="@drawable/case_resource_transport_top_bg"
        app:layout_constraintTop_toTopOf="parent" />

...
</android.support.constraint.ConstraintLayout>

activity AndroidManifest设置

1
2
3
4
   <activity android:name="....xxActivity"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.imgFullScreen"
        android:windowSoftInputMode="adjustPan"/>

stayles.xml 添加style

1
2
3
4
5
<style name="AppTheme.imgFullScreen">
    <item name="android:windowTranslucentStatus">false</item>
    <item name="android:windowTranslucentNavigation">false</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

xxActivity添加

1
2
3
4
5
val decorView = window.decorView

val option = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
decorView.systemUiVisibility = option
window.statusBarColor = Color.TRANSPARENT

效果: ./6.png

Android去除顶部默认的标题栏

当我们在Android Studio中创建一个新的Android项目时,会发现顶部有一个标题栏。我们有的时候并不需要这个标题栏,因此我们就需要把它去掉。

./8.png

在Android Studio中展开Project模块,会看到里面是一个由文件和文件夹构成的树形图。打开里面的app->manifests->AndroidManifest.xml文件,然后找到application标签的android:theme属性,把它的值改为"@style/Theme.AppCompat.NoActionBar",这样就可以解决问题了。

./9.png

Android注册服务

broadcastReceiver使用时需要在AndroidManifest.xml注册格式为

1
2
3
4
5
package="com">
<activity android:name=".MainActivity">
    ……
</activity>
<service android:name=".XXX" />

此处.目录取决于上面package导入的目录

Android TextView 文字居中

有2种方法可以设置TextView文字居中:

一:在xml文件设置:android:gravity=“center”

二:在程序中设置:m_TxtTitle.setGravity(Gravity.CENTER);

android给View设置上下左右边框

需求 设置view上下右有边框(左边不要边框),右上角右下角需要设置为圆角(左边不需要)

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- This is the main color -->
    <item>
        <shape>
            <!--    边框颜色 -->
            <solid android:color="@color/flash_text_normal"/>
        </shape>
    </item>
    <!-- 给View的上 下  右设置8dp的边框 -->
    <!-- http://blog.csdn.net/lowprofile_coding/article/details/47848245-->
    <item android:top="1dip" android:bottom="1dip" android:right="1dip" >
        <shape>
            <!--     View填充颜色 -->
            <solid android:color="@color/public_round_yellow" />
            <corners 
                 android:topRightRadius="@dimen/x10"  
                 android:bottomRightRadius="@dimen/x10"  />
        </shape>
    </item>

</layer-list>

./10.jpg

android 为TextView添加边框

今天需要在TextView上面添加一个边框,但是TextView本身不支持边框,所以只能采用其他方式,在网上查询了一下,主要有三种方式可以实现1.带有边框的透明图片2.使用xml的shape设置3继承TextView覆写onDraw方法。

方法一

带有透明图片的背景图,这个没有什么好将的,自己制作一个就行 ,然后设置background就可以了

方法二

  • 通过shape来设置背景图片

  • 首先一个textview_border.xml文件放在drawable文件夹里面

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
   <solid android:color="#ffffff" />
   <stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
  • 为要添加边框的TextView添加一个background android:background="@drawable/textview_border"

效果图片如下:

./11.png

方法三

编写一个继承TextView类的自定义组件,并在onDraw事件方法中画边框。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.test;
 
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;
 
@SuppressLint("DrawAllocation")
public class BorderTextView extends TextView{
 
	public BorderTextView(Context context) {
		super(context);
	}
	public BorderTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	private int sroke_width = 1;
	@Override
	protected void onDraw(Canvas canvas) {
		Paint paint = new Paint();
        //  将边框设为黑色
        paint.setColor(android.graphics.Color.BLACK);
        //  画TextView的4个边
        canvas.drawLine(0, 0, this.getWidth() - sroke_width, 0, paint);
        canvas.drawLine(0, 0, 0, this.getHeight() - sroke_width, paint);
        canvas.drawLine(this.getWidth() - sroke_width, 0, this.getWidth() - sroke_width, this.getHeight() - sroke_width, paint);
        canvas.drawLine(0, this.getHeight() - sroke_width, this.getWidth() - sroke_width, this.getHeight() - sroke_width, paint);
		super.onDraw(canvas);
	}
}

效果图如下:

./12.png

使用的Xml布局内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView 
    android:layout_width="120dp"
    android:layout_height="80dp"
    android:background="@drawable/textview_border"
    android:text="方法二"
    android:textColor="#FF000000"
    android:id="@+id/test"
    android:gravity="center"
    android:layout_alignParentTop="true"
    android:layout_marginTop="20dp"
    android:layout_centerHorizontal="true"/>
 
	<com.example.test.BorderTextView
      android:layout_width="120dp"
      android:layout_height="80dp"
      android:text="方法三"
      android:id="@+id/test3"
      android:gravity="center"
      android:layout_alignParentBottom="true"
      android:layout_marginBottom="20dp"
      android:layout_centerHorizontal="true">
    </com.example.test.BorderTextView>
</RelativeLayout>

全局变量

切换Fragment时有些值需要保存,故需要一个全局变量进行保存

​ 项目开发的过程中,可能会大量的使用全局变量,在android开发中,大多数人更偏向于使用application来保存全局变量。那么我们就先来了解下在android中,application究竟是什么?有什么作用?

  Application类是用来维护应用程序全局状态。我们可以提供自己的实现,并在AndroidManifest.xml文件的标签中指出它的名字,这将导致在创建应用程序时去实例化我们自己的Application类。Android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例模式的一个类。且Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局唯一的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以,通过Application来进行一些数据传递、数据共享、数据缓存等操作。

  首先创建继承自Application的MusicPlayerStatus类,定义变量update、current,并创建get和set方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import android.app.Application;

public class MusicPlayerStatus extends Application {
    private int update=-1;
    private int current=-1;

    public int getUpdate() {
        return update;
    }

    public void setUpdate(int update) {
        this.update = update;
    }

    public int getCurrent() {
        return current;
    }

    public void setCurrent(int current) {
        this.current = current;
    }
}

下面就是如何使用我们创建的全局变量了,在MainActivity中,首先要获得MusicPlayerStatus的对象,因为MusicPlayerStatus继承自Application,所以使用getApplication()方法即可,然后可以调用MusicPlayerStatus的get或set方法进行访问全局变量。

1
2
3
4
5
public MusicPlayerStatus musicPlayerStatus=new MusicPlayerStatus();
int update = musicPlayerStatus.getUpdate();
int current = musicPlayerStatus.getCurrent();
musicPlayerStatus.setUpdate(update);
musicPlayerStatus.setCurrent(current);

注意,在使用MusicPlayerStatus之前需要修改AndroidManifest.xml文件的中的android:name = “.MusicPlayerStatus”,这样就不会访问系统提供的application,而访问我们自己创建的。

Android 使控件各占屏幕的一半

在xml中将两个要占屏幕一半的控件都加上android:layout_weight=“1”;

注意:weight只能用在LinearLayout布局中。

在LinearLayout布局中weight数值越大显示的优先权就越低。

Fragment生命周期

相互切换时调用的方法

一、前言:

Fragment生命周期图如下:

./13.png

二、Fragment 1 切换到 Fragment 2时生命周期变化

1. 通过 add hide show 方式来切换 Fragment

  • Fragment1 的生命周期变化为:onCreate()、onCreateView、onStart()、onResume() 回调 onHiddenChanged() 方法
  • Fragment2 的生命周期变化为: onCreate()、onCreateView、onStart()、onResume()
  • Fragment 2 再次返回到 Fragment 1:不走任何生命周期方法但是回调 onHiddenChanged()方法

总结:当以这种方式进行 Fragment 1 与 Fragment 2 的切换时,Fragment 隐藏的时候并不走 onDestroyView,所有的显示也不会走 onCreateView 方法,所有的 view 都会保存在内存。

2. 使用 replace 的方法进行切换时

  • 载入Fragment 1时: Fragment 1的生命周期:onCreate()、onCreateView()、onStart()、onResume()
  • 切换到Fragment2时: Fragment 1的生命周期:onPause()、onStop()、onDestroyView()、onDestroy() Fragment 2的生命周期:onCreate()、onCreateV()、onStart()、onResume()
  • Fragment 2切换回Fragment 1时: Fragment2的生命周期:onPause()、onStop()、onDestroyView()、onDestroy() Fragment 1的生命周期:onCreate()、onCreateV()、onStart()、onResume()

总结:通过 replace 方法进行替换的时,Fragment 都是进行了销毁,重建的过程,相当于走了一整套的生命周期。

3. 使用 ViewPager 进行切换时

当使用 ViewPager 与 Fragment 进行切换时,Fragment 会进行预加载操作 所有的 Fragment 都会提前初始—>预加载;

初始化时 Fragment 们的生命周期:

Fragment 1 的生命周期:onCreate()、onCreateView() Fragment 2 的生命周期:onCreate()、 onCreateView()

  • Fragment 1 切换到 Fragment 2 的生命周期:

Fragment 1 :不走任何生命周期; Fragment 2 :走 setUserVisVleHint()方法

切回去也是一样的 注意: setUserVisVleHint()方法在 Fragment 1 第一次加载的时候不走,只有在切换的时候 走该方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
/**
*第一个 Fragment 需要处理  setUserVisVleHint()方法,设置为 setUserVisibleHint(true);
*否则会产空指针异常,因为 setUserVisVleHint()方法的优先级高于 onCreate()方法。
*
* @param savedInstanceState
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    setUserVisibleHint(true);
    super.onActivityCreated(savedInstanceState);
}
 /*
主动调用 setUserVisibleHint()方法来控制第一次不会调用setUserVisibleHint方法的问题。
setUserVisibleHint()方法优先onCreateView方法,当onCreateView方法调用后还会再次调用setUserVisibleHint方法。
此时要对是否调用了onCreateView()方法进行标记判断。
*/

三、其它切换

1. Activity 切换到 Fragment 的生命周期变化

  • Fragment 的生命周期变化为:onStart()、onResume()

2. 从 Fragment 1 进行锁屏操作

  • Fragment 的生命周期方法:onPause()、onSaveInstanceState()、onStop()。

3. 从解锁 到 Fragment 1 的生命周期

  • onStart()、 onResume()

简单实现ImageView宽度填满屏幕,高度自适应的两种方式

两种方式

1.重写View的onMeasure方法

核心代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
     Drawable d = getDrawable();
     if(d!=null){
         // ceil not round - avoid thin vertical gaps along the left/right 
         edgesintwidth = MeasureSpec.getSize(widthMeasureSpec);
         //高度根据使得图片的宽度充满屏幕计算而得 
         intheight = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
     setMeasuredDimension(width, height);
     }else{
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 }

2.设置ImageView的属性:

1
2
3
4
5
6
//宽度填满屏幕
 android:layout_width=”match_parent”
 android:scaleType=”fitXY”
 android:layout_height=”wrap_content”
 //保持比例,一定要设置
 android:adjustViewBounds=”true”

Android使用Bundle+Message+Hundle进行线程间通信

数据是java自带数据对象(常规八种数据结构)

接收线程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public Handler mHandler=new Handler(){  
        public void handleMessage(Message msg) {  
        switch(msg.what){  
            case CANSHU :   String str1 = msg.getData().getString("text1");//接受msg传递过来的参数   
                    String str2 = msg.getData().getString("text2");//接受msg传递过来的参数   
                    initFinishMainActivity(str1, str2);  
                              break;  
            default         : break;  
            }  
        }     
    };  

发送线程

1
2
3
4
5
6
7
Message msg = new Message();  
            msg.what = MainActivity.CANSHU;  
            Bundle bundle = new Bundle();    
                      bundle.putString("text1","大明的消息传递参数的例子!");  //往Bundle中存放数据   
                         bundle.putString("text2","Time:2011-09-05");  //往Bundle中put数据   
                         msg.setData(bundle);//mes利用Bundle传递数据   
                         activity.mHandler.sendMessage(msg);//用activity中的handler发送消息   

数据是自定义对象时

自定义类

首先需要自定对象实现Serializable可序列化的接口,如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class Persion implements Serializable {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接收线程

getString等改为

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public Handler mHandler=new Handler(){  
        public void handleMessage(Message msg) {  
        switch(msg.what){  
            case CANSHU :   
                Persion persion=(Persion)(msg.getData().getSerializable("persion"));
                //接受msg传递过来的参数
                initFinishMainActivity(persion);  
                break;  
            default: 
                break;  
            }  
        }     
    };  

发送线程

putString等改为putSerializable

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Message msg = new Message();  
msg.what = MainActivity.CANSHU; 
Persion persion=new Persion();
String Name="zhangsan";
persion.setName(Name);
Bundle bundle = new Bundle();    
bundle.putSerializable("persion",persion); 
//往Bundle中存放数据   
msg.setData(bundle);//mes利用Bundle传递数据   
activity.mHandler.sendMessage(msg);//用activity中的handler发送消息   

Android历史版本平台、SDK、版本名称对照(争取持续更新)

平台版本 SDK版本 版本名称
12.0 31 Android 12(Snow Cone)(刨冰)
11.0 30 Red Velvet Cake(Quince Tart)(Android R)(11)(红丝绒蛋糕)
10.0 29 (Android Q)(10)
9.0 28 Pie (Android P)(派/馅饼)
8.1 27 Oreo(Android O)(奥利奥)
8.0 26 [Oreo(Android O)(奥利奥)
7.1 25 Nougat(Android N)(牛轧糖)
7.0 24 Nougat(Android N)(牛轧糖)
6.0 23 Marshmallow(Android M)(棉花糖)
5.1 22 Lollipop(Android L)(棒棒糖)
5.0 21 Lollipop(Android L)(棒棒糖)
4.4W 20 KITKAT Wear(奇巧巧克力)
4.4 19 [KITKAT(奇巧巧克力)
4.3 18 JELLY_BEAN_MR2(软心豆粒糖/果冻豆)
4.2 / 4.2.2 17 JELLY_BEAN_MR1(软心豆粒糖)
4.1 / 4.1.1 16 JELLY_BEAN(软心豆粒糖)
4.0.3 / 4.0.4 15 ICE_CREAM_SANDWICH_MR1(冰淇淋三明治)
4.0 / 4.01 / 4.02 14 ICE_CREAM_SANDWICH(冰淇淋三明治)
3.2 13 HONEYCOMB_MR2(蜂巢)
3.1.X 12 HONEYCOMB_MR1(蜂巢)
3.0.X 11 HONEYCOMB(蜂巢)
2.3.3 / 2.3.4 10 GINGERBREAD_MR1(姜饼)
2.3 9 GINGERBREAD(姜饼)
2.2 / 2.2.1 8 Froyo(冻酸奶)
2.1 7 Eclair_MR2(闪电泡芙)
2.0.1 6 Eclair_MR1(闪电泡芙)
2.0 5 Eclair(闪电泡芙)
1.6 4 Donut(甜甜圈)
1.5 3 Cupcake(纸杯蛋糕)
1.1 2 Petit Four
1.0 1 Astro / Bender(1.0有两版)

Android资源管理器注意事项

/data/user/0是/data/data目录的软连接或者是快捷方式

ImageView / ImageButton 图片太大或者太小

第一步:指定layout_width与layout_height 在xml文件中设置的ImageButton的宽和高为:

1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
    <ImageButton
        android:layout_width="100dp"
        android:layout_height="100dp"/>

第二步:设置属性android:scaleType ImageView的属性android:scaleType,即 ImageView.setScaleType(ImageView.ScaleType)。android:scaleType是控制图片如何 resized/moved来匹对ImageView的size。ImageView.ScaleType / android:scaleType值的意义区别:

ImageButton属性 ImageButton解释
CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长 (宽)等于或大于View的长(宽)
CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
FIT_XY / fitXY 把图片 不按比例 扩大/缩小到View的大小显示
scaleType属性 scaleType说明
CENTER /center 在视图中心显示图片,并且不缩放图片
CENTER_CROP / centerCrop 按比例缩放图片,使得图片长 (宽)的大于等于视图的相应维度
CENTER_INSIDE / centerInside 按比例缩放图片,使得图片长 (宽)的小于等于视图的相应维度
FIT_CENTER / fitCenter 按比例缩放图片到视图的最小边,居中显示
FIT_END / fitEnd 按比例缩放图片到视图的最小边,显示在视图的下部分位置
FIT_START / fitStart 把图片按比例扩大/缩小到视图的最小边,显示在视图的上部分位置
FIT_XY / fitXY 把图片不按比例缩放到视图的大小显示
MATRIX / matrix 用矩阵来绘制

end