“条条大路通罗马。”工做中,实现某个需求的方式每每不是惟一的,这些不一样实现方式不只表如今代码质量上,还影响着咱们的工做效率。就像,在 Android 系统中,总有那么一些不为人知的 API 可以减小咱们不少零碎的工做量。因而,就想凭着一些经验,整理一些经常使用的,找个地方概括总结,也供往后翻阅。html
根据资源名称获取资源 id。正常状况下,咱们会在代码中直接根据资源ID获取资源,好比:java
getResources().getDrawable(R.drawable.ic_launcher);复制代码
但有时候,资源并非固定的,须要根据使用状况从多个同类资源中动态选择,好比根据服务器传递给客户端的接口数据动态设置,怎么办呢?设置一个硬编码的映射关系数组?太繁琐!不妨用上这个方法。android
一个完整的资源名为package:type/entry
,对应该方法的三个参数:资源名称、资源类型、应用包名。举几个例子:程序员
imageView.setImageResource(getResources().getIdentifier("ic_launcher", "drawable", getPackageName()));
radioGroup.check(getResources().getIdentifier("rb_indicator_" + position, "id", getPackageName()));复制代码
实际使用过程当中,第一个参数 name,也就是资源名称,根据须要动态设置,这就须要多个资源在命名时保持必定的规范格式。另外,须要注意的是,直接经过 id 获取资源比经过名字的方式效率更高,因此,若是没有这般特殊需求的话,不提倡使用这个方法获取资源。web
使用频率超高的字符串判空方法,返回一个 boolean 值,内部实现的判断条件为:str == null || str.length() == 0
。备受开发人员喜好的一个 if 字符串判断,系统已经帮咱们封装过。正则表达式
解析 Html 格式的富文本内容,并返回一个带样式的字符串,供 TextView 等控件显示。能够解决一些含超连接、图文混排等格式的富文本内容的显示问题。算法
利用 Android SDK 提供的这个日期工具类能够将 long 类型的毫秒级时间数据格式化成特定显示格式的字符串。一般咱们使用 Java SDK 中的 SimpleDateFormat
格式化日期数据,好比 new SimpleDateFormat("yyyy-MM-dd HH:mm").format()
,DateUtils
的做用就是替咱们封装了这个过程。格式化结果与当前设备的本地语言环境有关。这里列举几个经常使用 format 格式(中文环境下):canvas
格式化文件大小,将字节数据格式化为 B、KB、M 等单位的相应数据。context 参数用于判断返回结果的字符串顺序,right-to-left 仍是 left-to-right 形式的。这个工具类免去咱们本身转化计算的过程,很是方便,特别适用于应用内文件下载的相似场景。数组
将指定单位的尺寸数据按照当前设备屏幕信息转化为相应的像素值。其中,TypedValue 为第一个参数提供了经常使用的单位值,好比:安全
源码以下:
public static float applyDimension(int unit, float value, DisplayMetrics metrics){
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}复制代码
其实在实际使用过程当中,像素值都是 int 整数类型,而该方法返回的是 float 类型,若是直接强制转换的话,会自动舍去小数部分。因此,若是不用该方法的话,一般咱们会这么转换:
public static int convertDipToPx(Context context, int dip) {
float scale = context.getResources().getDisplayMetrics().density;
// 0.5f 用于向上取整
return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
}复制代码
官方注释以下:
Space is a lightweight View subclass that may be used to create gaps between components in general purpose layouts.
Space 是一个用于建立视图之间空隙的轻量级 View。在 onDraw() 方法中不执行任何绘制,因此 android:background
属性对他来讲不起做用。一般咱们使用 View 建立视图间的空隙,在不考虑背景色的状况下,Space 其实效率更高。注意,因为是 API 14 引入的控件,若是须要向前兼容的话,须要使用到 support v4 包。
自动调用 View 点击事件。一般按钮等控件只有在用户点击时才能触发其点击事件,该方法能够由某些特殊条件触发模拟用户点击行为。相似的还有 performLongClick()
方法。
Log
类提供的一个公共静态方法,与常见的 Log.i()
等方法打印日志到 logcat 控制台不一样的是,该方法从 Throwable 对象中获取错误信息,并以字符串的形式返回。当你须要作错误信息的数据持久化,好比保存至本地存储卡中或者上传至服务器时,利用这个方法就很是方便。
咱们知道对于 TextView 文本控件中的内容,经过 android:autoLink
属性能够为其添加诸如 web、phone 等固定模版的超连接点击事件。但毕竟系统模版有限,而利用 Linkify.addLinks()
方法能够添加一些应用内自定义模版,好比新浪微博中的 "@XXX" 格式的超连接跳转等,均可以经过自定义正则表达式来匹配处理。
设置安全窗口,禁用系统截屏。防止 App 中的一些界面被截屏,并显示在其余设备中形成信息泄漏。(常见手机设备系统截屏操做方式为:同时按下电源键和音量键。)
好比支付宝 App 的“向商家付款”的包含付款二维码的界面。(补充说明一点,微信付款界面不是这么作的,采用的是在 onResume() 生命周期方法中实时刷新付款二维码,与支付宝在安全方法采起的手段不一样。)
@Override
public void onBackPressed() {
Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
launcherIntent.addCategory(Intent.CATEGORY_HOME);
startActivity(launcherIntent);
}复制代码
使用 Back 键返回桌面,但不关闭当前应用,而是使之进入后台,就像按下 Home 键同样。
这个技巧厉害了。一般为了防止出现用户误按 Back 键退出 App 的状况,咱们会在应用首页的 Activity 中监听返回键操做,使用 Toast 弱提示甚至 Dialog 强提示的方式给到用户一个再次确认的操做,但没法阻止用户经过返回键逐步关闭应用。
然而,若是用这个方法拦截 App 最后一个 Activity(常见为首页界面),既没有阻碍用户操做(回到桌面),又没有关闭掉咱们的应用(后台运行中),间接提升 App 的存活时间,真乃暗度陈仓。而且据我实验,微信、支付宝、微博等 App 都是这么作的,你们不妨一试。
缩略图工具类,能够根据本地视频文件源、Bitmap 对象生成缩略图,经常使用的公共静态方法为:
从源 bitmap 中根据 alpha 获取一个新的 bitmap 对象。比较绕口,一般 App 中的 Icon 多数是纯色透明像素背景组成,利用这个方法能够对该图的非透明区域着色,有多种使用场景,常见如 Button 的 pressed 状态,View 的阴影状态等。举个例子:
private static Bitmap getDropShadow(ImageView iv, Bitmap src, float radius, int color) {
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(color);
final int width = src.getWidth(), height = src.getHeight();
final Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(dest);
final Bitmap alpha = src.extractAlpha();
canvas.drawBitmap(alpha, 0, 0, paint);
final BlurMaskFilter filter = new BlurMaskFilter(radius, BlurMaskFilter.Blur.OUTER);
paint.setMaskFilter(filter);
canvas.drawBitmap(alpha, 0, 0, paint);
iv.setImageBitmap(dest);
return dest;
}复制代码
系统提供的一个 TypeEvaluator ,咱们只须要提供两个起始颜色值和一个分值,系统会经过特定的算法计算得出一个新的颜色中间值。利用这个类,咱们至少能够作两件事情。
第一,用于属性动画中。因为其实现了 TypeEvaluator
接口,能够用来作自定义属性动画的求值器,改变 View 的显示状态。好比:
int colorStart = ContextCompat.getColor(this, R.color.black);
int colorEnd = ContextCompat.getColor(this, R.color.green);
ValueAnimator valueAnimator = ValueAnimator
.ofObject(new ArgbEvaluator(), colorStart, colorEnd)
.setDuration(3000);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
textView.setTextColor((Integer) animation.getAnimatedValue());
}
});
valueAnimator.start();复制代码
第二,利用该类提供的颜色求值算法,配合 ViewPager
提供的滑动偏离值使用。这种场景常见于使用 ViewPager
实现的引导页,其背景色随着滑动距离动态改变;使用 ViewPager
实现的 Tab 样式菜单页面,Tab 中文本内容随着滑动距离动态改变字体颜色(能够参考安卓版微信)。这两种使用都使得 ViewPager
页面切换过渡得很天然,体验极佳。如:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
new ArgbEvaluator().evaluate(positionOffset, startColor, endColor);
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});复制代码
另外,关于颜色差值的计算,Google Sample 里有另外一种算法,可参考 SlidingTabStrip.java 文件源码,核心方法内容以下:
/** * Blend {@code color1} and {@code color2} using the given ratio. * * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, * 0.0 will return {@code color2}. */
private static int blendColors(int color1, int color2, float ratio) {
final float inverseRation = 1f - ratio;
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
return Color.rgb((int) r, (int) g, (int) b);
}复制代码
用于 LinearLayout
中,用于设置 Children weight 的总比重。在 LinearLayout
的 children 中,咱们常常会使用 android:layout_weight
按比例分配容器布局的空间,但有时候不必定会分完。以往,有些朋友可能会使用一个空
用于 ViewGroup 中,解决做为 Parent 的 ViewGroup 与 Children View 之间的焦点占用问题。最最多见的使用场景就是 list item 中含有一些点击效果的控件,好比 Button、CheckBox 等,相信你们都遇到过。取值有三种,含义就不用再多说了:
是否将 View 自身的 drawable state 交给直接 parent ViewGroup 控制,值为 boolean 类型。好比有一个 item 布局,item 中有一个 button,若是点击 item layout 时,须要 button 呈现对应的点击效果,就能够在 button 中用到这个属性。不过,从设计的角度来说,这种场景仍是比较少见的。知道有这个属性就好,不推荐这种交互设计。
ScrollView 的一个属性,用于设置内容部分是否填满屏幕,主要针对内容不足以填满屏幕的状况。这里推荐一个使用技巧,参考我以前写的文章:Android 平常开发中,两个很是实用的布局技巧。
使用 ImageView 时,你可能会用 android:scaleType
属性设置图片缩放方式。却不知,android:adjustViewBounds
属性也能起到相似的效果。但要注意的是,后者须要至少指定 ImageView 宽高中的一个属性,或者 maxHeight 之类的,而后另外一个属性随之适配。这个属性用在列表中较为合适,好比 App 中的活动列表页面,图片宽度设置为 match_parent,而后高度设为 wrap_content 使其自适应,这样便能保证从服务获取的高分辨率图片在不一样的屏幕中不被拉伸变形。(备注:最好在项目资源文件中放置一个与网络图片相同尺寸的默认图,起到 placeholder 做用,避免图片显示前高度为 0 的较差体验。)
本文先记这么多吧,日积月累,后续持续更新中,敬请关注...(固然,你有什么高效而又少见的 API,欢迎一块儿分享交流哦~)
安卓笔记侠:专一于 Android 开发,和程序员之路。