赞
踩
//获取对应索引位置的Drawable对象
if (selectDrawable(idx)) {
return true;
}
…
}
该函数的主要功能: 根据新的状态值,从StateListDrawable实例对象中,找到第一个完全吻合该新状态值的索引下标处 ;
继而,调用selectDrawable()方法去获取索引下标的当前Drawable对象。
具体查找算法在 mStateListState.indexOfStateSet(stateSet) 里实现了。基本思路是:查找第一个能完全吻合该新状态值
的索引下标,如果找到了,则立即返回。 具体实现过程,只好看看源码咯。
Step 3 、selectDrawable()函数原型:
该函数位于 frameworks\base\graphics\java\android\graphics\drawable\StateListDrawable.java 类中
public boolean selectDrawable(int idx)
{
if (idx >= 0 && idx < mDrawableContainerState.mNumChildren) {
//获取对应索引位置的Drawable对象
Drawable d = mDrawableContainerState.mDrawables[idx];
…
mCurrDrawable = d; //mCurrDrawable即使当前Drawable对象
mCurIndex = idx;
…
} else {
…
}
//请求该View刷新自己,这个方法我们稍后讲解。
invalidateSelf();
return true;
}
该函数的主要功能是选择当前索引下标处的Drawable对象,并保存在mCurrDrawable中。
知识点三: 关于Drawable.Callback接口
该接口定义了如下三个函数:
//该函数位于 frameworks\base\graphics\java\android\graphics\drawable\Drawable.java 类中
public static interface Callback {
//如果Drawable对象的状态发生了变化,会请求View重新绘制,
//因此我们对应于该View的背景Drawable对象能够”绘制出来”.
public void invalidateDrawable(Drawable who);
//
public void scheduleDrawable(Drawable who, Runnable what, long when);
//
public void unscheduleDrawable(Drawable who, Runnable what);
}
其中比较重要的函数为:
public voidinvalidateDrawable(Drawable who)
函数功能:如果Drawable对象的状态发生了变化,会请求View重新绘制,因此我们对应于该View的背景Drawable对象
能够重新”绘制“出来。
Android框架View类继承了该接口,同时实现了这三个函数的默认处理方式,其中invalidateDrawable()方法如下:
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource
{
…
//Invalidates the specified Drawable.
//默认实现,重新绘制该视图本身
public void invalidateDrawable(Drawable drawable) {
if (verifyDrawable(drawable)) { //是否是同一个Drawable对象,通常为真
final Rect dirty = drawable.getBounds();
final int scrollX = mScrollX;
final int scrollY = mScrollY;
//重新请求绘制该View,即重新调用该View的draw()方法 …
invalidate(dirty.left + scrollX, dirty.top + scrollY,
dirty.right + scrollX, dirty.bottom + scrollY);
}
}
…
}
因此,我们的Drawable类对象必须将View设置为回调对象,否则,即使改变了状态,也不会显示对应的背景图。 如下:
Drawable d ; // 图片资源
d.setCallback(View v) ; // 视图v的背景资源为 d 对象
知识点四:View绘制背景图片过程
在前面的博客中《Android中View绘制流程以及invalidate()等相关方法分析》,我们知道了一个视图的背景绘制过程时在
View类里的draw()方法里完成的,我们这儿在回顾下draw()的流程,同时重点讲解下绘制背景的操作。
//方法所在路径:frameworks\base\core\java\android\view\View.java
//draw()绘制过程
private void draw(Canvas canvas){
//该方法会做如下事情
//1 、绘制该View的背景
//其中背景图片绘制过程如下:
//是否透明, 视图通常是透明的 , 为true
if (!dirtyOpaque) {
//开始绘制视图的背景
final Drawable background = mBGDrawable;
if (background != null) {
final int scrollX = mScrollX; //获取偏移值
final int scrollY = mScrollY;
//视图的布局坐标是否发生了改变, 即是否重新layout了。
if (mBackgroundSizeChanged) {
//如果是,我们的Drawable对象需要重新设置大小了,即填充该View。
background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
mBackgroundSizeChanged = false;
}
//View没有发生偏移
if ((scrollX | scrollY) == 0) {
background.draw(canvas); //OK, 该方法会绘制当前StateListDrawable的当前背景Drawable
} else {
//View发生偏移,由于背景图片值显示在布局坐标中,即背景图片不会发生偏移,只有视图内容onDraw()会发生偏移
//我们调整canvas对象的绘制区域,绘制完成后对canvas对象属性调整回来
canvas.translate(scrollX, scrollY);
background.draw(canvas); //OK, 该方法会绘制当前StateListDrawable的当前背景Drawable
canvas.translate(-scrollX, -scrollY);
}
}
}
…
//2、为绘制渐变框做一些准备操作
//3、调用onDraw()方法绘制视图本身
//4、调用dispatchDraw()方法绘制每个子视图,dispatchDraw()已经在Android框架中实现了,在ViewGroup方法中。
//5、绘制渐变框
}
That’s all ! 我们用到的知识点也就这么多吧。 如果大家有丝丝不明白的话,可以去看下源代码,具体去分析下这些流程到底
是怎么走下来的。
我们从宏观的角度分析了View绘制不同状态背景的原理,View框架就是这么做的。为了易于理解性,
下面我们通过一个小Demo来演示前面种种流程。
Demo 说明:
我们参照View框架中绘制不同背景图的实现原理,自定义一个View类,通过给它设定StateListDrawable对象,使其能够在
不同状态时能动态"绘制"背景图片。 基本流程方法和View.java类实现过程一模一样。
截图如下:
初始背景图 触摸后显示的背景图(pressed)
一、主文件MainActivity.java如下:
/**
@author http://http://blog.csdn.net/qinjuning
*/
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(MainActivity.this);
CustomView customView = new CustomView(MainActivity.this);
//简单设置为 width 200px - height 100px吧
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(200 , 100);
customView.setLayoutParams(lp);
//需要将该View设置为可点击/触摸状态,否则触摸该View没有效果。
customView.setClickable(true);
ll.addView(customView);
setContentView(ll);
}
}
功能很简单,为Activity设置了视图 。
二、 自定义View如下 , CustomView.java :
/**
*/
//自定义View
public class CustomView extends View /extends Button/
{
private static String TAG = “TackTextView”;
private Context mContext = null;
private Drawable mBackground = null;
private boolean mBGSizeChanged = true;; //视图View布局(layout)大小是否发生变化
public CustomView(Context context)
{
super(context);
mContext = context;
initStateListDrawable(); // 初始化图片资源
}
// 初始化图片资源
private void initStateListDrawable()
{
//有两种方式获取我们的StateListDrawable对象:
// 获取方式一、手动构建一个StateListDrawable对象
StateListDrawable statelistDrawable = new StateListDrawable();
int pressed = android.R.attr.state_pressed;
int windowfocused = android.R.attr.state_window_focused;
int enabled = android.R.attr.state_enabled;
int stateFoucesd = android.R.attr.state_focused;
//匹配状态时,是一种优先包含的关系。
// "-"号表示该状态值为false .即不匹配
statelistDrawable.addState(new int[] { pressed, windowfocused },
mContext.getResources().getDrawable(R.drawable.btn_power_on_pressed));
statelistDrawable.addState(new int[]{ -pressed, windowfocused },
mContext.getResources().getDrawable(R.drawable.btn_power_on_nor));
mBackground = statelistDrawable;
//必须设置回调,当改变状态时,会回掉该View进行invalidate()刷新操作.
mBackground.setCallback(this);
//取消默认的背景图片,因为我们设置了自己的背景图片了,否则可能造成背景图片重叠。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
自己的知识准备得怎么样,这直接决定了你能否顺利通过一面和二面,所以在面试前来一个知识梳理,看需不需要提升自己的知识储备是很有必要的。
关于知识梳理,这里再分享一下我面试这段时间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)
资料获取方式:前往我的GitHub
知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结:
《960全网最全Android开发笔记》
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
.(img-nGaJFfic-1711325629742)]
知识梳理完之后,就需要进行查漏补缺,所以针对这些知识点,我手头上也准备了不少的电子书和笔记,这些笔记将各个知识点进行了完美的总结:
[外链图片转存中…(img-XNHsC599-1711325629742)]
《960全网最全Android开发笔记》
[外链图片转存中…(img-sJdjcIeX-1711325629743)]
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
[外链图片转存中…(img-U58LN7Pg-1711325629743)]
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。