码迷,mamicode.com
首页 > 移动开发 > 详细

Android--自定义控件(三)

时间:2015-11-15 22:56:06      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17045157

视图状态以及重绘

View 是有状态的。比如点击的时候,点击一下就变了个样子。

一、视图状态

一共有十几种类型,我们只会使用到其中的几种

1. enabled

表示当前视图是否可用。可以调用setEnable()方法来改变视图的可用状态,传入true表示可用,传入false表示不可用。它们之间最大的区别在于,不可用的视图是无法响应onTouch事件的。

2. focused

表示当前视图是否获得到焦点。通常情况下有两种方法可以让视图获得焦点,

即通过键盘的上下左右键切换视图,以及调用requestFocus()方法。而现在的Android手机几乎都没有键盘了,

因此基本上只可以使用requestFocus()这个办法来让视图获得焦点了。而requestFocus()方法也不能保证一定可以让视图获得焦点,它会有一个布尔值的返回值,如果返回true说明获得焦点成功,返回false说明获得焦点失败。一般只有视图在focusablefocusable in touch mode同时成立的情况下才能成功获取焦点,比如说EditText

3. window_focused

表示当前视图是否处于正在交互的窗口中,这个值由系统自动决定,应用程序不能进行改变。

4. selected

表示当前视图是否处于选中状态。一个界面当中可以有多个视图处于选中状态,调用setSelected()方法能够改变视图的选中状态,传入true表示选中,传入false表示未选中。

5. pressed

表示当前视图是否处于按下状态。可以调用setPressed()方法来对这一状态进行改变,传入true表示按下,传入false表示未按下。通常情况下这个状态都是由系统自动赋值的,但开发者也可以自己调用这个方法来进行改变。

我们可以在项目的drawable目录下创建一个selector文件,在这里配置每种状态下视图对应的背景图片。比如创建一个compose_bg.xml文件,在里面编写如下代码:

<selector xmlns:android="http://schemas.android.com/apk/res/android">  
  
    <item android:drawable="@drawable/compose_pressed" android:state_pressed="true"></item>  
    <item android:drawable="@drawable/compose_pressed" android:state_focused="true"></item>  
    <item android:drawable="@drawable/compose_normal"></item>  
  
</selector>  

 

这段代码就表示,当视图处于正常状态的时候就显示compose_normal这张背景图,当视图获得到焦点或者被按下的时候就显示compose_pressed这张背景图。

 

创建好了这个selector文件后,我们就可以在布局或代码中使用它了,比如将它设置为某个按钮的背景图,如下所示:

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical" >  
      
    <Button   
        android:id="@+id/compose"  
        android:layout_width="60dp"  
        android:layout_height="40dp"  
        android:layout_gravity="center_horizontal"  
        android:background="@drawable/compose_bg"  
        />  
      
</LinearLayout>  

 

每当视图的状态发生改变的时候,就会回调ViewdrawableStateChanged()方法

protected void drawableStateChanged() {  
    Drawable d = mBGDrawable;  
    if (d != null && d.isStateful()) {  
        d.setState(getDrawableState());  
    }  
}  

 

 

二、视图重绘

虽然视图会在Activity加载完成之后自动绘制到屏幕上,但是我们完全有理由在与Activity进行交互的时候要求动态更新视图,比如改变视图的状态、以及显示隐藏某个控件等。那在这个时候,之前绘制出的视图其实就已经过期了,此时我们就应该对视图进行重绘。

调用视图的setVisibility()、setEnabled()、setSelected()等方法时都会导致视图重绘,而如果我们想要手动地强制让视图进行重绘,可以调用invalidate()方法来实现。当然了,setVisibility()、setEnabled()、setSelected()等方法的内部其实也是通过调用invalidate()方法来实现的,那么就让我们来看一看invalidate()方法的代码是什么样的吧。

View的源码中会有数个invalidate()方法的重载和一个invalidateDrawable()方法,当然它们的原理都是相同的,因此我们只分析其中一种,代码如下所示:

void invalidate(boolean invalidateCache) {  
    if (ViewDebug.TRACE_HIERARCHY) {  
        ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);  
    }  
    if (skipInvalidate()) {    //用它判断视图是否需要重绘。
        return;  
    }  
    if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||  
            (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||  
            (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {  
        mLastIsOpaque = isOpaque();  
        mPrivateFlags &= ~DRAWN;  
        mPrivateFlags |= DIRTY;  
        if (invalidateCache) {  
            mPrivateFlags |= INVALIDATED;  
            mPrivateFlags &= ~DRAWING_CACHE_VALID;  
        }  
        final AttachInfo ai = mAttachInfo;  
        final ViewParent p = mParent;  //这里的viewParent的invalidateChild()
        if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {  
            if (p != null && ai != null && ai.mHardwareAccelerated) {  
                p.invalidateChild(this, null);  
                return;  
            }  
        }  
        if (p != null && ai != null) {  
            final Rect r = ai.mTmpInvalRect;  
            r.set(0, 0, mRight - mLeft, mBottom - mTop);  
            p.invalidateChild(this, r);  
        }  
    }  
}  

 

Android--自定义控件(三)

标签:

原文地址:http://www.cnblogs.com/zrui513/p/4967527.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!