Android 开发小技巧

Android 开发小技巧

前言

做了许久的开发,常常有些小细节会打动到我,希望这篇文章可以记录这些分享给大家

布局文件

tools命名空间在预览布局时的应用

在布局编写时常常因查看布局效果会添加一些正式环境不会初始化的属性,比如说 text,visibility... 但是为了初始化效果,这些属性一般会在完成后删除,有时候在维护时为了方便预览再写上,这时可以使用 tools 的命名空间。如

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:text="这段话只在预览时�展示,正式环境不会显示" />

在运行的状态下解析布局文件时就会忽略 tools 属性

android.widget.Space 占位控件

一个占位轻量级控件,绘制过程中会跳过 onDraw() 步骤,使用与分隔不同的控件展示一片空白

Merge 合并标签

此标签可以节省一层布局深度。常常运用在 include 标签之中,一般情况下我们将 include 的根标签用 merge 代替,而不用再新建一个 ViewGroup,同时在自定义继承自系统ViewGroups时在写布局文件时也需要用到,可以避免一层布局深度;可以通过载入一个带有标签的布局文件来自动定义它的子部件

<merge
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:parentTag="android.widget.RelativeLayout"     

通过 tools:parentTag 可以预览富布局效果

android:duplicateParentState (View属性)

当改属性设置为true时,子View可以复制父View的状态(selected,focused等状态)。比如如果一个ViewGroup是可点击的,那么可以用这个�属性在它被点击的时候让它的子View都改变状态

android:clipChildren (ViewGroup属性)

定义了子View是否仅限于在Padding里绘制。此属性默认设置为true即子View绘制无法超过ViewGroup的padding区域,当设置为false时,那么ViewGroup的子View在绘制的时候会超出它的范围,往往会在做动画的时候需要用到

android:clipToPadding (ViewGroup属性)

定义了ViewGroup是否会裁剪子View调整边缘效果保证padding效果,当ViewGroup设置了padding后该属性默认为true。
运用场景:有时�ScrollView,RecyclerView等会设置一个离顶部toolbar及屏幕底部一定距离来留白,�默认情况下,滚动是在padding范围内的,会出现内容的上下滚动边界离真正的边界有一定的距离。此时只需要将该属性设置为false,滚动时子控件就能�绘制到父控件的padding区域

android:animateLayoutChanges (ViewGroup属性)

ViewGroup中添加或移除View时(对Visibility设置也起作用)设置动画的办法,支持通过setLayoutTransition()自定义动画

android:fillViewport (ScrollView属性)

�该属性�决定了滚动视图是否应该伸展它的内容填补视窗。就是要让ScrollView内部元素的match_parent起作用将该属性设置为true

app:layoutManager (RecyclerView属性)

RecyclerView 可以在 xml 布局文件中设置 LayoutManager,可以不用在代码中创建新的 LayoutManager 实例,RecyclerView 在 style 中已定义

<declare-styleable name="RecyclerView">
    <attr name="layoutManager" format="string"/>
    <attr name="android:orientation"/>
    <attr name="spanCount" format="integer"/>
    <attr name="reverseLayout" format="boolean"/>
    <attr name="stackFromEnd" format="boolean"/>
</declare-styleable>

TextView

TextView.setError()

可以设置文字或者文字加上图片,展示一个 popupWindow 效果非常好

TextView去除上下留白

TextView 默认上下是有一定的 padding 的,有时候我们可能不需要上下这部分留白,在 xml 布局文件中加上 includeFontPadding="false" 即可

TextView设置图片

xml布局文件中设置:

<TextView
    ......
    android:drawableLeft = "@�drawable/icon"/>

或者可以在 �java 代码文件中设置:

Drawable img = ContextCompat.getDrawable(this, R.drawable.icon);
img.setBounds(0,0,100,100);
textView.setCompoundDrawables(img,null,null,null);

/* ********* or ********* */
Drawable img = ContextCompat.getDrawable(this, R.drawable.icon);
textView.setCompoundDrawablesWithIntrinsicBounds(�img,null,null,null);

/* ********* or ********* */
textView.setCompoundDrawablesWithIntrinsicBounds(resId,0,0,0);

TextView在文中设置特殊格式

setText(CharSequence text) 方法可以传入 SpannableString 类展示特殊格式,该类通过 setSpan(Object what, int start, int end, int flags) 方法可以设置各种不同的效果,比如说颜色,背景,点击事件等等,建议通过 SpannableStringBuilder 类得到实例或者 fromHtml(String source)� 方法得到。

EditView

InputType

可以定义软键盘弹出的类型,在xml布局文件中的EditText标签下直接定义,比如说定义带小数的数字输入

<EditText 
    ......
    android:inputType="number" />

也可以在 java 代码中设置

editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);

可以在 xml 文件中设置 android:inputType="textUri" 或者代码中调用 setInputType(InputType.TYPE_TEXT_VARIATION_URI)实现英文键盘弹出

setKeyListener(KeyListener)

通过 DigitsKeyListener 类,使用 getInstance(String accepted) 方法即可指定EditText可输入字符集
同时也在代码中可以通过 setFilters(InputFilter[] filters) 设置过滤器来实现 EditText 的定向输入。比如说两位小数的输入的自定义 InputFilter

public class DecFilter implements InputFilter {
    @Override
    public CharSequence filter(CharSequence source,
                               int start, int end, Spanned dest, int dstart, int dend) {
        //不能在倒数第三位以前输入点
        if (".".equals(source.toString()) && dstart + 2 < dest.length()) return "";
        //控制小数位数为两位
        String[] splitArray = dest.toString().split("\\.");
        if (splitArray.length > 1) {
            //如果已经含有两位小数,判断插入的地方是否为小数位,是则过滤
            if (splitArray[1].length() == 2 && dstart + 2 >= dest.length()) {
                return "";
            } else {
                return source;
            }
        }
        return source;
    }
}

与InputType配合可以实现两位小数输入限制

软键盘适配

为了解决弹出软键盘遮挡 EditText 的冲突,一般会在 manifests 文件对应 activity 标签下添加

<activity
    ......
    android:windowSoftInputMode="adjustPan|stateAlwaysHidden"/>

但在 EditView 为多行输入且文本高度超过控件高度时,当隐藏键盘后点击超过控件高度的文本位置时,软键盘的弹出会遮盖 EditText,此时需要将 adjustPan 替换成 adjustResize

点击外部隐藏软键盘

可以在activity的基类的 dispatchTouchEvent(MotionEvent ev) 中添加如下方法:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {    
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {    
        View v = getCurrentFocus();        
        if (v != null && (v instanceof EditText)) {           
            int[] point = {0, 0};            
            v.getLocationOnScreen(point);            
            int left = point[0], top = point[1], bottom = top + v.getHeight(), right = left + v.getWidth();            
            if (!(ev.getRawX() > left && ev.getRawX() < right && ev.getRawY() > top && ev.getRawY() < bottom)) {                
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);                
                imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);                
                v.clearFocus();
            }       
        }    
    }    
return super.dispatchTouchEvent(ev);}

软键盘的监听

Android 系统并没有提供软键盘监听接口,但某些场景却需要对键盘进行监听,此时可以采用特殊的办法,那就是采用 Activity 的

public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)                             

当 Activity 的键盘属性是 adjustResize 时,键盘弹出会挤压 activity 的布局,此时可以通过 (bottom - oldBottom > keyHeight) 方法来认为键盘是否弹出,keyHeight 一般认为是屏幕高度的 1/3

RecyclerView

自动测量

在 Support Library 23.2 以后支持自动测量,现在可以非常方便将 Recycler 嵌套在 ScrollView 及其他 ViewGroup 中,可以设置 warp_content 用来自动测量

当嵌套在 ScrollView 中时,因为滑动方向一致导致 RecyclerView 部分会由粘滞感,需要调用方法 setNestedScrollingEnabled(false) 但在高 sdk 上有bug,此时的 RecyclerView 未加载的 item 将不会显示,解决办法是将 ScrollView 替换成 NestedScrollView

自定义View

列举一些对自定义View有帮助的类或方法

  • canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
    该方法可以用来清除画布上的内容

  • canvas.clipRect()、clipPath()
    该方法可以用来剪切画布区域

  • onDetachedFromWindow
    复写该方法中清理与 View 相关的资源

  • getParent().requestDisallowInterceptTouchEvent(true)
    方法可以剥夺父 View 对 touch 事件的处理权,可用于滑动冲突

  • ArgbEvaluator.evaluate
    用于根据一个起始颜色值和一个结束颜色值以及一个偏移量生成一个新的颜色,�可用于自定义 View 的动画

  • ViewDragHelper
    用于自定义 ViewGroup 处理各种事件

  • GestureDetector
    用来监听和相应对应的手势事件,比如点击,长按,慢滑动,快滑动

  • ViewConfiguration.getScaledTouchSlop()
    触发移动事件的最小距离,这是系统提供的用于自定义 View 处理 touch 事件的时候判断用户是否滑动的最小距离

  • StaticLayout
    该类一般用于在自定义 View 中渲染文字

  • Paint.setXfermode(porterDuffXfermode)
    在 ApiDemo 里面有专门的介绍,实现了穿透,叠加,覆盖等多种绘制效果,非常实用

  • performClick() 和 performLongClick()
    方法可以分别模拟View的点击和长按

  • VelocityTracker
    可用于 View 滑动事件速度跟踪

其他

Fragment 类中的 onHiddenChanged(boolean) 方法

该会在 FragmentTransaction 的 hide() 和 show() 调用时被 Fragment 调用,而 Fragment 的其他生命周期方法并不会在此时被调用,所以一般的刷新等操作不能在 onResume() 方法中实现

Fragment.setArguments(Bundle bundle)

在构建 Fragment 的时候不能加参数,我们可以通过将参数传入 Bundle 中,通过此方法传入到 Fragment 实例中(即使在 configuration 改变的时候仍然会导致销毁/重建)

FragmentManager.enableDebugLogging()

可以帮助观察 Fragment 状态

PageTransformer 接口

可以用来定义 ViewPager 页面切换的动画,通过 setPageTransformer(boolean, PageTransformer) 方法实现

Resources 类中的 getIdentifier(name,defType,defPackage)

方法可以通过资源名称获取其ID,可以在多种不同类型资源获取中运用

ViewStub

该类是一个初始化不做任何事情的 View,但是之后可以载入一个布局文件。在慢加载 View 中很适合做占位符。唯一的缺点就是不支持标签,所以如果你不太小心的话,可能会在视图结构中加入不需要的嵌套

View保存为Bitmap

除了ScrollView外可以使用下面方法:

public static Bitmap createBitmap(View v) {
    v.setDrawingCacheEnabled(true);
    v.buildDrawingCache();
    Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
    v.setDrawingCacheEnabled(false);
    return bitmap;
}

而ScrollView则需要使用下面方法:

public static Bitmap createBitmap(ScrollView v) {
    int width = 0, height = 0;
    for (int i = 0; i < v.getChildCount(); i++) {
        width += v.getChildAt(i).getWidth();
        height += v.getChildAt(i).getHeight();
    }
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    v.draw(canvas);
    return bitmap;
}

android.text.TextUtils

该类集成了许多关于字符串的常用方法。比如说判断字符串是否为 null 或 "" 的 isEmpty(CharSequence) 方法;判断字符串是否相同的 equals(CharSequence a, CharSequence b) 方法(使用 a.equals(b) 方法需要对 a 做非空判断)等

android.util.Pair

该类可以存储一组数据,但并不是以key-value形式存在,而是两个参数单独存在

android.graphics.PointF

该类可以用来描述坐标点,比起单独的x,y更加方便简洁,还包括了一些简单的坐标计算函数

android.util.SparseArray

当 key 为 int 类型时,SparseArray 可以用来替换 hashMap,它可以避免操作数据池时的大量装箱拆箱过程以便节省内存,提高性能。还有一些继承类 SparseBooleanArray、SparseIntArray 和 SparseLongArray

android.database.DatabaseUtils

类是用于提供操作数据库的�通用方法

java.math.BigDecimal

该类是用于高精度计算的类,可以直接传入字符串,返回�类型和格式可以通过相关方法自定义,较复杂的计算推荐这个类。这个类有一个相关的 DecimalFormat 类,用于字串格式化包括指定位数、百分数、科学计数法等

感谢

Android开发中,有哪些让你觉得相见恨晚的方法、类或接口
awesome-android-tips

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

推荐阅读更多精彩内容