安卓开发需要注意/知道的小问题

  1. android:descendantFocusability属性,其中翻译成中文意思是子孙焦点,也就是当前 viewgroup 和其子控件谁获取当前焦点的意思。常用在 listview 和 recyclerView 中,当 listView 每个条目需要监听点击事件,同时每个条目里的子控件例如:button、checkbox 等也需要点击焦点的时候。

此属性对应的值有三个,分别是

beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点 

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

官方文档对此说明是:

android:descendantFocusabilityDefines the relationship between the ViewGroup and its descendants when looking for a View to take focus.Must be one of the following constant values.


对应的值.jpg
  1. Android 里 canvas.draw() 方法需要注意的:
    当画矩形 canvas.drawRect() 时如果是空心的矩形,即设置了 paint.setStyle(Paint.Style.STROKE) 和 paint.setStrokeWidth(20) 属性,则要注意矩形起始点和右下角坐标位置应该分别减去线条宽度的一半,即
canvas.drawRect(strokeWidth/2,strokeWidth/2,width-strokeWidth/2,height-strokeWidth/2,paint);  //左上右下,画笔

举个例子 参考来源

矩形画布.png

如果在上图位置画一个 50*100dp 的矩形(见下图),其中线条宽度是20dp,起始左上角坐标和结束右下角坐标不是(0,0)和 (100,50),此时应该注意线条宽度也占据了位置,起始位置应该加上线条宽度的一半,终点位置应该减去线条宽度的一半,也就是取线条的中间。这里就是

canvas.drawRect(10,10,90, 40, paint);  //这里暂不考虑 dp 转 px 的分辨率问题,都当成 px 处理。
需要实现的矩形

延伸

①.如果画矩形不设置 stroke 属性,直接设置 paint.setStyle(Style.FILL),则直接从红色矩形左上角坐标点开始即可;

②.如果画圆,也设置了描边,如下图,那么画圆的时候半径就是布局的一半减去线条宽度的一半。


圆.png

③.如果画线,即 canvas.drawLine(),如下图所示,如果设置 paint.setStrokeWidth(20),
则表示画线的线条粗细为 20px ,那么画的时候坐标点就是图中红点,即左边界线条的中间点,即(0,10)这个点;


线条
  1. 全面屏手机显示 view 的时候,部分手机底部有留白或者黑边,也就是没有铺满屏幕显示。
    其实只要设置项目的 targetSdkVersion > 24,即大于 7.0,则默认支持全面屏,也就不会有黑边显示。如果项目是比较老的版本,并且 targetSdkVersion < 24 且不好随便更改,也可以在 manifest 文件里配置以下内容:
<meta-data
            android:name="android.max_aspect"
            android:value="2.4" />

这样也可以做到全屏展示。为什么这里 value 是 2.4,其实这是计算出来的一个预估值,因为传统屏幕:ratio_float = 16/9 = 1.778 ;像小米的 MIX2 是 18 / 9 =2 的,mix3 是 19.5 / 9 = 2.16,越来越长可以写稍微大点留一些余地,所以直接写成 2.4 更保险一些。以后开发估计都会支持全面屏,并且 Google 支持把 targetSdkVersion 写成最新版本,所以基本上以后的项目不会涉及到全面屏显示不全的问题,因为 targetSdkVersion 大于 24 已经默认支持了全面屏显示。

  1. 安卓中三个获取定义的 dimens 值的方法:
  getDimension、getDimensionPixelOffset 和 getDimensionPixelSize

在开发中,在代码里动态设置布局的间距、尺寸等数值时,最好使用 /res/values/dimens.xml 里的自定义尺寸,这样可以做到不同分辨率的屏幕适配,因为可以定义不同的 dimens 文件对应不同的分辨率。现在就看下上边三种方法对应获取的值的区别。

首先说明三个方法返回的都是对应的像素值,也就是不管定义的是 dp 还是 sp 或者 px,返回的都是 px 单位的值,可以通过以下的例子来看:

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="dp_value">17dp</dimen>
    <dimen name="sp_value">17sp</dimen>
    <dimen name="px_value">17px</dimen>
</resources>

        //获取屏幕信息
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        float density = displayMetrics.density;
        int densityDpi = displayMetrics.densityDpi;
        System.out.println("屏幕宽:"+ width + "屏幕高:"+height);
        System.out.println("屏幕密度:"+ density + "屏幕密度 DPI:" + densityDpi);


        float a1 = getResources().getDimension(R.dimen.px_value);
        float a2 = getResources().getDimension(R.dimen.dp_value);
        float a3 = getResources().getDimension(R.dimen.sp_value);
        System.out.println("getDimension 中 px值是:" + a1);
        System.out.println("getDimension 中 dp值是:" + a2);
        System.out.println("getDimension 中 sp值是:" + a3);

        int b1 = getResources().getDimensionPixelSize(R.dimen.px_value);
        int b2 = getResources().getDimensionPixelSize(R.dimen.dp_value);
        int b3 = getResources().getDimensionPixelSize(R.dimen.sp_value);
        System.out.println("getDimensionPixelSize 中 px值是:" + b1);
        System.out.println("getDimensionPixelSize 中 dp值是:" + b2);
        System.out.println("getDimensionPixelSize 中 sp值是:" + b3);

        int c1 = getResources().getDimensionPixelOffset(R.dimen.px_value);
        int c2 = getResources().getDimensionPixelOffset(R.dimen.dp_value);
        int c3 = getResources().getDimensionPixelOffset(R.dimen.sp_value);
        System.out.println("getDimensionPixelOffset 中 px值是:" + c1);
        System.out.println("getDimensionPixelOffset 中 dp值是:" + c2);
        System.out.println("getDimensionPixelOffset 中 sp值是:" + c3);

打印数据是:

2019-07-28 17:43:27.469 23912-23912/com.ispring.gameplane I/System.out: 屏幕宽:1080 屏幕高:2030
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: 屏幕密度:2.75屏幕密度 DPI:440
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 px值是:17.0
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 dp值是:46.75
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimension 中 sp值是:46.75
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 px值是:17
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 dp值是:47
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelSize 中 sp值是:47
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 px值是:17
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 dp值是:46
2019-07-28 17:43:27.470 23912-23912/com.ispring.gameplane I/System.out: getDimensionPixelOffset 中 sp值是:46

通过结果可以看出,获取某个 dimen 的值,如果单位是 dp 或者 sp ,需要乘以 density (屏幕密度),如果是 px ,则不需要。

不同点:
getDimension:返回的是 float 类型的值。
getDimensionPixelSize: 返回的是 int 类型的值,并且由浮点型转成整型时是四舍五入的方式。
getDimensionPixelOffset : 返回的是 int 类型的值,并且由浮点型转成整型时,原则是忽略小数点部分。

  1. textView 在代码中设置粗体可以这样设置:
TextView tv = (TextView)findViewById(R.id.TextView01);  
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true); 

取消加粗效果的话设置
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(false);

  1. android:clipToPadding属性的用法

在使用 ListView 或者 RecycleView、ScrollView 等滑动控件时候有一个强大但隐秘的属性,在android 的布局 XML 文件中,android:clipToPadding=“boolean”,该属性值可设为 true 或者false。表示控件的绘制区域是否在 padding 里面,true 的情况下如果你设置了 padding 那么绘制的区域就往里缩,false 则表示滑动时忽略 padding 的值。系统默认是 true。

属性的作用就是当你对 ListView 等滑动控件设置了 padding 属性后,四周会有缩进的效果,正常会与屏幕四边有空白间距,然后滑动的时候此间距一直显示。如果设置 android:clipToPadding=“false” ,则在滑动的时候间距自动随着滑动布局上滑以致不会显示空白间距,此时也就有了比较好的用户体验。

效果就是下边两张图所示:第一张为默认情况,即 android:clipToPadding =“true”,第二张为 false 时的结果。


true结果.png
false结果.png
  1. ColorStateList 可以设置文字颜色在不同状态下切换的功能,不需要手动根据不同状态设置不同的颜色值,使用方法如下:

首先,定义一个 selector 的选择器

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/color_ffffff" android:state_enabled="true" android:state_selected="true" />
    <item android:color="@color/color_2f9cf6"/>
</selector>

在代码中使用方法如下:

ColorStateList csl=(ColorStateList)getResources().getColorStateList(R.color.button_text);  
Button btn =  new Button(mContext);
btn.setTextColor(csl);

也可以直接在布局文件中设置 android:textColor = "@color/button_text" 来实现。

此外,还有个 StateListDrawable 与 ColorStateList 类似,只不过它是设置 drawable 类型的资源文件,并且设置的资源文件是放在 res/drawable/ 文件夹下,静态使用方法如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@drawable/button_pressed" /> <!-- pressed -->
    <item android:state_focused="true"
          android:drawable="@drawable/button_focused" /> <!-- focused -->
    <item android:state_hovered="true"
          android:drawable="@drawable/button_focused" /> <!-- hovered -->
    <item android:drawable="@drawable/button_normal" /> <!-- default -->
</selector>
<Button
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:background="@drawable/button" />

也可以动态代码构造一个 StateListDrawable ,例如:

//初始化一个空对象
StateListDrawable stalistDrawable = new StateListDrawable();
//获取对应的属性值 Android框架自带的属性 attr
int pressed = android.R.attr.state_pressed;
int window_focused = android.R.attr.state_window_focused;
int focused = android.R.attr.state_focused;
int selected = android.R.attr.state_selected;
stalistDrawable.addState(newint []{pressed , window_focused}, getResources().getDrawable(R.drawable.pic1));
//负值表示对应的属性是 false, 下边的属性即按下状态但没有获取焦点的时候
stalistDrawable.addState(newint []{pressed , -focused}, getResources().getDrawable(R.drawable.pic2);
stalistDrawable.addState(newint []{selected }, getResources().getDrawable(R.drawable.pic3);
stalistDrawable.addState(newint []{focused }, getResources().getDrawable(R.drawable.pic4);
//没有任何状态时显示的图片,我们给它设置我空集合
stalistDrawable.addState(newint []{}, getResources().getDrawable(R.drawable.pic5);

动态使用方法:

   StateListDrawable states = new StateListDrawable();
   states.addState(new int[] {-android.R.attr.state_pressed}, INTERSTITIAL_CLOSE_BUTTON_NORMAL.createDrawable( getContext()));
    states.addState(new int[] {android.R.attr.state_pressed}, INTERSTITIAL_CLOSE_BUTTON_PRESSED.createDrawable(
                getContext()));
    mImageView.setImageDrawable(states);
  1. 异常的处理和抛出:throw与throws以及捕捉异常try、catch、finally
    1、throws出现在方法函数头;而throw出现在函数体。
    2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
    3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
    4、throws说明你有那个可能,倾向。throw的话,那就是你把那个倾向变成真实的了。
    5、举例:throws E1,E2,E3只是告诉程序这个方法可能会抛出这些异常,方法的调用者可能要处理这些异常,而这些异常E1,E2,E3可能是该函数体产生的。
    throw则是明确了这个地方要抛出这个异常。
    举个例子:
void function_throws(int a,int b) throws Exception1,Exception3{
           try{
                 ......
           }catch(Exception1 e){
              throw e;
           }catch(Exception2 e){
              System.out.println("出错了!");
           }
           if(a!=b)
              throw new  Exception3("自定义异常");
}

代码块中可能会产生3个异常,(Exception1,Exception2,Exception3)。
如果产生 Exception1 异常,则捕获之后再抛出,由该方法的调用者去处理。
如果产生 Exception2 异常,则该方法自己处理了(即System.out.println("出错了!");)。所以该方法就不会再向外抛出 Exception2 异常了,即 throws Exception1,Exception3 里面不用写 Exception2 异常。

抛出异常后的语句都不会执行,try catch finally 里 finally 不管怎样都会执行。

  1. 申请权限时,在 Fragment 中申请权限,不要使用这种方式
ActivityCompat.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);

直接使用 Fragment 的 requestPermissions 方法,即

requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);

否则会回调到 Activity 的 onRequestPermissionsResult ,使用第二种方法会直接在 Fragment 里回调。

如果在 Fragment 中嵌套 Fragment,在子 Fragment 中使用 requestPermissions 方法,onRequestPermissionsResult 不会回调回来,建议在子 Fragment 中使用 getParentFragment().requestPermissions 方法,
这个方法会回调到父 Fragment 中的 onRequestPermissionsResult(),加入以下代码可以把回调透传到子 Fragment。

 @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        List<Fragment> fragments = getChildFragmentManager().getFragments();
        if (fragments != null) {
            for (Fragment fragment : fragments) {
                if (fragment != null) {
                    fragment.onRequestPermissionsResult(requestCode,permissions,grantResults);
                }
            }
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容