日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android中CheckBox与CompoundButton源码解析

發(fā)布時(shí)間:2024/8/1 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android中CheckBox与CompoundButton源码解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

經(jīng)歷過了前面一系列的講解,下面我們直接來看看系統(tǒng)里面的CheckBox與CompoundButton類的源碼文件。你肯定會(huì)發(fā)現(xiàn)很多熟悉的地方。
結(jié)合下面源碼,我們對(duì)它們進(jìn)行解析解析,它里面使用的就是自定義drawable state。

我們首先直接看CheckBox的源碼

public class CheckBox extends CompoundButton {public CheckBox(Context context) {this(context, null);}public CheckBox(Context context, AttributeSet attrs) {this(context, attrs, com.android.internal.R.attr.checkboxStyle);}public CheckBox(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overridepublic void onInitializeAccessibilityEvent(AccessibilityEvent event) {super.onInitializeAccessibilityEvent(event);event.setClassName(CheckBox.class.getName());}@Overridepublic void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {super.onInitializeAccessibilityNodeInfo(info);info.setClassName(CheckBox.class.getName());} }

我們可以看到,它里面并沒有做什么,因?yàn)樗牟僮鞫际抢^承自CompoundButton.

我們先來看看下面一個(gè)普通的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:paddingBottom="@dimen/activity_vertical_margin"tools:context=".MainActivity"><CheckBoxandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="CheckBox"/></RelativeLayout>

在上面的這個(gè)相對(duì)布局中,就寫了一個(gè)CheckBox,我們什么都不做,直接運(yùn)行代碼,就會(huì)看到下面的運(yùn)行界面:

當(dāng)我們單擊這個(gè)CheckBox,我們發(fā)現(xiàn)他會(huì)被選中,那么它內(nèi)部到底是怎么實(shí)現(xiàn)的呢?
其實(shí)使用過drawable state的人應(yīng)該對(duì)這個(gè)并不陌生,我們經(jīng)常這樣做:

1、在res/drawable文件下創(chuàng)建selector.xml,示例代碼如下:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_pressed="false"android:drawable="@drawable/title_button_back"></item><item android:state_pressed="true"android:drawable="@drawable/title_button_back_h"></item><item android:state_window_focused="false"android:drawable="@drawable/title_button_back"></item> </selector>

2、編寫布局文件,為布局文件中的ImageButton設(shè)置selector,示例代碼如下:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="fill_parent"> <ImageButton android:id="@+id/title_IB"android:layout_height="wrap_content" android:layout_width="wrap_content" android:background="#00000000" android:layout_marginRight="4dp" android:layout_centerVertical="true" android:src="@drawable/selector"></ImageButton> </RelativeLayout>

當(dāng)我們單擊這個(gè)圖片按鈕的時(shí)候,圖片按鈕的圖片就會(huì)發(fā)生變化,其實(shí)CheckBox也是這樣做的,只是這些系統(tǒng)為我們做了。

下面我們來看看系統(tǒng)實(shí)現(xiàn)源碼:
上面在布局文件中直接寫了一個(gè)CheckBox,布局文件被解析后就會(huì)實(shí)例化這個(gè)CheckBox對(duì)象,就會(huì)執(zhí)行CheckBox的構(gòu)造函數(shù):

public CheckBox(Context context, AttributeSet attrs) {this(context, attrs, com.android.internal.R.attr.checkboxStyle); }public CheckBox(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle); }

從上面我們可以知道兩點(diǎn):
1、CheckBox的默認(rèn)樣式是com.android.internal.R.attr.checkboxStyle
2、最終執(zhí)行的時(shí)候CompoundButton的構(gòu)造函數(shù)

在frameworks/base/core/res/res/values/themes.xml文件中,已經(jīng)初始化了checkBoxStyle樣式:

<item name="checkboxStyle">@android:style/Widget.CompoundButton.CheckBox</item>

在frameworks/base/core/res/res/values/styles.xml文件,我們來看看它的樣式是什么:

<style name="Widget.CompoundButton.CheckBox"><item name="android:button">?android:attr/listChoiceIndicatorMultiple</item> </style>

在frameworks/base/core/res/res/values/themes.xml文件:

<item name="listChoiceIndicatorMultiple">@android:drawable/btn_check</item>

可以看到,CheckBox的默認(rèn)樣式就是給它的button屬性賦值了一個(gè)btn_check,我們來看看btn_check文件里面的具體內(nèi)容。

在frameworks/base/core/res/res/drawable/btn_check.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"><!-- Enabled states --><item android:state_checked="true" android:state_window_focused="false"android:state_enabled="true"android:drawable="@drawable/btn_check_on" /><item android:state_checked="false" android:state_window_focused="false"android:state_enabled="true"android:drawable="@drawable/btn_check_off" /><item android:state_checked="true" android:state_pressed="true"android:state_enabled="true"android:drawable="@drawable/btn_check_on_pressed" /><item android:state_checked="false" android:state_pressed="true"android:state_enabled="true"android:drawable="@drawable/btn_check_off_pressed" /><item android:state_checked="true" android:state_focused="true"android:state_enabled="true"android:drawable="@drawable/btn_check_on_selected" /><item android:state_checked="false" android:state_focused="true"android:state_enabled="true"android:drawable="@drawable/btn_check_off_selected" /><item android:state_checked="false"android:state_enabled="true"android:drawable="@drawable/btn_check_off" /><item android:state_checked="true"android:state_enabled="true"android:drawable="@drawable/btn_check_on" /><!-- Disabled states --><item android:state_checked="true" android:state_window_focused="false"android:drawable="@drawable/btn_check_on_disable" /><item android:state_checked="false" android:state_window_focused="false"android:drawable="@drawable/btn_check_off_disable" /><item android:state_checked="true" android:state_focused="true"android:drawable="@drawable/btn_check_on_disable_focused" /><item android:state_checked="false" android:state_focused="true"android:drawable="@drawable/btn_check_off_disable_focused" /><item android:state_checked="false" android:drawable="@drawable/btn_check_off_disable" /><item android:state_checked="true" android:drawable="@drawable/btn_check_on_disable" /></selector>

我們看到,state_checked為true的時(shí)候,drawable=”@drawable/btn_check_on”,state_checked為false的時(shí)候,drawable=”@drawable/btn_check_off”.
@drawable/btn_check_on圖片和@drawable/btn_check_off圖片,在frameworks/base/core/res/res/drawable我們可以找到:

我們可以看到,其實(shí)就是根據(jù)不同的狀態(tài),為button屬性賦值了不同的圖片資源,這就是我們看到的效果。

state_checked這個(gè)狀態(tài)的定義,在下面進(jìn)行了定義:

<declare-styleable name="DrawableStates"><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a view has input focus. --><attr name="state_focused" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a view's window has input focus. --><attr name="state_window_focused" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a view is enabled. --><attr name="state_enabled" format="boolean" /><!-- State identifier indicating that the object <var>may</var> display a check mark.See {@link R.attr#state_checked} for the identifier that indicates whether it isactually checked. --><attr name="state_checkable" format="boolean"/><!-- State identifier indicating that the object is currently checked. See{@link R.attr#state_checkable} for an additional identifier that can indicate ifany object may ever display a check, regardless of whether state_checked iscurrently set. --><attr name="state_checked" format="boolean"/><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a view (or one of its parents) is currently selected. --><attr name="state_selected" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when the user is pressing down in a view. --><attr name="state_pressed" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a view or its parent has been "activated" meaning the user has currentlymarked it as being of interest. This is an alternative representation ofstate_checked for when the state should be propagated down the view hierarchy. --><attr name="state_activated" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.--><attr name="state_active" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.--><attr name="state_single" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.--><attr name="state_first" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.--><attr name="state_middle" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable}.--><attr name="state_last" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},indicating that the Drawable is in a view that is hardware accelerated.This means that the device can at least render a full-screen scaledbitmap with one layer of text and bitmaps composited on top of itat 60fps. When this is set, the colorBackgroundCacheHint will beignored even if it specifies a solid color, since that optimizationis not needed. --><attr name="state_accelerated" format="boolean" /><!-- State value for {@link android.graphics.drawable.StateListDrawable StateListDrawable},set when a pointer is hovering over the view. --><attr name="state_hovered" format="boolean" /><!-- State for {@link android.graphics.drawable.StateListDrawable StateListDrawable}indicating that the Drawable is in a view that is capable of accepting a drop ofthe content currently being manipulated in a drag-and-drop operation. --><attr name="state_drag_can_accept" format="boolean" /><!-- State for {@link android.graphics.drawable.StateListDrawable StateListDrawable}indicating that a drag operation (for which the Drawable's view is a valid recipient)is currently positioned over the Drawable. --><attr name="state_drag_hovered" format="boolean" /><!-- State for {@link android.graphics.drawable.StateListDrawable StateListDrawable}indicating that a View has accessibility focus. --><attr name="state_accessibility_focused" format="boolean" /> </declare-styleable>

我們可以看到<attr name="state_checked" format="boolean"/>

下面我們看看CompoundButton的構(gòu)造函數(shù),因?yàn)镃heckBox最終執(zhí)行的是它的構(gòu)造函數(shù)。

public CompoundButton(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a =context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0);Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);if (d != null) {setButtonDrawable(d);}boolean checked = a.getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false);setChecked(checked);a.recycle(); }

我們可以知道CompoundButton自定義了兩個(gè)屬性,進(jìn)入frameworks/base/core/res/res/values/attrs.xml文件:

<declare-styleable name="CompoundButton"><!-- Indicates the initial checked state of this button. --><attr name="checked" format="boolean" /><!-- Drawable used for the button graphic (e.g. checkbox, radio button, etc). --><attr name="button" format="reference"/> </declare-styleable>

我們可以看到它定義了兩個(gè)屬性:checked,button,一個(gè)存放的是一個(gè)boolean類型的值,表示是否被選中,一個(gè)存放的是引用類型,對(duì)應(yīng)的是一個(gè)圖片。
在構(gòu)造函數(shù)中,我們獲取到了這兩個(gè)屬性值。上面就是對(duì)button這個(gè)屬性進(jìn)行了默認(rèn)賦值,然后我們這里就可以獲取到上面的btn_check這個(gè)xml文件的drawable。
也就是說Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button)中的d的到的就是btn_check這個(gè)xml文件的drawable。

然后分別調(diào)用了setButtonDrawable(d)和setChecked(checked)來對(duì)我們自定義的控件進(jìn)行了設(shè)置。

我們來看看setButtonDrawable(d)函數(shù):

public void setButtonDrawable(Drawable d) {if (d != null) {if (mButtonDrawable != null) {mButtonDrawable.setCallback(null);unscheduleDrawable(mButtonDrawable);}//這里設(shè)置Callback的原因就是refreshDrawableState刷新的時(shí)候可以回調(diào)到invalidateDrawable//這樣就可以重繪,這個(gè)我們?cè)?詳解refreshDrawableList()的執(zhí)行流程#這篇文件講過d.setCallback(this);d.setVisible(getVisibility() == VISIBLE, false);mButtonDrawable = d;setMinHeight(mButtonDrawable.getIntrinsicHeight());}refreshDrawableState(); }

最后調(diào)用了refreshDrawableState這個(gè)方法,這個(gè)執(zhí)行過程我們也分析過,整個(gè)執(zhí)行思路都是一樣,不過不同的是,里面的很多方法都被覆蓋了。

這里我們?cè)賮戆颜麄€(gè)思路走一走。

refreshDrawableState執(zhí)行的還是View里面的這個(gè)方法,直接看源碼。

public void refreshDrawableState() {//首先把標(biāo)志設(shè)置為PFLAG_DRAWABLE_STATE_DIRTYmPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;drawableStateChanged();ViewParent parent = mParent;if (parent != null) {parent.childDrawableStateChanged(this);} }

drawableStateChanged這個(gè)方法不在執(zhí)行View里面的這個(gè)方法,因?yàn)镃ompoundButton里面有這個(gè)方法,我們看看CompoundButton的這個(gè)方法。

@Override protected void drawableStateChanged() {super.drawableStateChanged();if (mButtonDrawable != null) {int[] myDrawableState = getDrawableState();// Set the state of the DrawablemButtonDrawable.setState(myDrawableState);invalidate();} }

getDrawableState這個(gè)函數(shù)還是調(diào)用的View的這個(gè)函數(shù)。

public final int[] getDrawableState() {//PFLAG_DRAWABLE_STATE_DIRTY是前面refreshDrawableState設(shè)置的//如果mDrawableState不為空,并且不需要刷新狀態(tài),則直接返回,否則重新進(jìn)行獲取if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {return mDrawableState;} else {//這里就是重新得到視圖狀態(tài),并將其返回mDrawableState = onCreateDrawableState(0);//清除前面refreshDrawableState設(shè)置的標(biāo)識(shí)mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;return mDrawableState;} }

下面調(diào)用到了onCreateDrawableState這個(gè)方法,這個(gè)方法也不在是執(zhí)行View里面的這個(gè)方法,因?yàn)镃ompoundButton里面也有這個(gè)方法。

@Override protected int[] onCreateDrawableState(int extraSpace) {final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);if (isChecked()) {mergeDrawableStates(drawableState, CHECKED_STATE_SET);}return drawableState; }

結(jié)合之前我們?cè)斀鈘efreshDrawableList()的執(zhí)行流程的分析。這個(gè)方法就是在之前的基礎(chǔ)上加入了一個(gè)判斷,如果isChekced為真,就把我們自定義的這個(gè)狀態(tài)加進(jìn)去,這樣當(dāng)前狀態(tài)里面就有我們的自定義的狀態(tài),后面在狀態(tài)二維數(shù)組中查詢的時(shí)候,就可以找到對(duì)應(yīng)的drawable圖片進(jìn)行設(shè)置了。

這個(gè)函數(shù)執(zhí)行完了就會(huì)回到上面的getDrawableState函數(shù),然后把當(dāng)前的狀態(tài)返回到drawableStateChanged函數(shù)中,接著看里面的代碼。

接著執(zhí)行mButtonDrawable.setState(myDrawableState),把得到的當(dāng)前狀態(tài)數(shù)組設(shè)置進(jìn)去。里面的執(zhí)行過去前面詳解refreshDrawableList()的執(zhí)行流程的分析也說過,是完全一樣的,我們就省略,不明白就再看看,最后會(huì)執(zhí)行invalidateSelf函數(shù)。

這個(gè)函數(shù)就會(huì)得到前面我們?cè)O(shè)置的Callback回調(diào),調(diào)用它的invalidateDrawable方法。

public void invalidateSelf() {final Callback callback = getCallback();if (callback != null) {callback.invalidateDrawable(this);} }

跟前面一樣,因?yàn)閂iew實(shí)現(xiàn)了這個(gè)回調(diào),所以它執(zhí)行的是View里面的實(shí)現(xiàn)方法。在這個(gè)方法里面執(zhí)行了invalidate函數(shù),所以會(huì)執(zhí)行onDraw方法.
在CompoundButton里面實(shí)現(xiàn)了這個(gè)方法,它不再直接執(zhí)行View里面的這個(gè)方法了。

protected void onDraw(Canvas canvas) {super.onDraw(canvas);final Drawable buttonDrawable = mButtonDrawable;if (buttonDrawable != null) {final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;final int drawableHeight = buttonDrawable.getIntrinsicHeight();final int drawableWidth = buttonDrawable.getIntrinsicWidth();int top = 0;switch (verticalGravity) {case Gravity.BOTTOM:top = getHeight() - drawableHeight;break;case Gravity.CENTER_VERTICAL:top = (getHeight() - drawableHeight) / 2;break;}int bottom = top + drawableHeight;int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;int right = isLayoutRtl() ? getWidth() : drawableWidth;buttonDrawable.setBounds(left, top, right, bottom);buttonDrawable.draw(canvas);} }

這樣這個(gè)圖片就繪制出來了,從btn_check里面我們可以看到最開始顯示的圖片是btn_check_off,當(dāng)我們單擊這個(gè)CheckBox的時(shí)候,會(huì)執(zhí)行performClick函數(shù)。

@Override public boolean performClick() {/** XXX: These are tiny, need some surrounding 'expanded touch area',* which will need to be implemented in Button if we only override* performClick()*//* When clicked, toggle the state */toggle();return super.performClick(); }

接著執(zhí)行toggle函數(shù)。

public void toggle() {setChecked(!mChecked); }

這里面就把當(dāng)前的狀態(tài)設(shè)置為與之前相反的狀態(tài),剛開始為false,這個(gè)時(shí)候就為true.

接著我們看看setChecked函數(shù)。

public void setChecked(boolean checked) {if (mChecked != checked) {mChecked = checked;refreshDrawableState();notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);// Avoid infinite recursions if setChecked() is called from a listenerif (mBroadcasting) {return;}mBroadcasting = true;if (mOnCheckedChangeListener != null) {mOnCheckedChangeListener.onCheckedChanged(this, mChecked);}if (mOnCheckedChangeWidgetListener != null) {mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);}mBroadcasting = false; } }

在這個(gè)里面又執(zhí)行了refreshDrawableState函數(shù),同樣把上面的refreshDrawableState過程又執(zhí)行了一遍,執(zhí)行在到onCreateDrawableState就不一樣了。
我們?cè)趤砜纯催@個(gè)函數(shù):

protected int[] onCreateDrawableState(int extraSpace) {final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);if (isChecked()) {mergeDrawableStates(drawableState, CHECKED_STATE_SET);}return drawableState; }

第一次執(zhí)行的時(shí)候isChecked為false,自定義的這個(gè)狀態(tài)沒有合進(jìn)去,這次就把自定義的這個(gè)狀態(tài)合進(jìn)去,這樣就可以查詢到我們的狀態(tài),所以就可以找到定義的drawable,所以圖片發(fā)生改變?yōu)閎tn_check_on。

最后把完整的CompoundButton源碼貼出來,可以對(duì)照上面將的,然后再根據(jù)前面講的詳解refreshDrawableList()的執(zhí)行流程這個(gè)過程理解理解。

/** Copyright (C) 2007 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.widget;import com.android.internal.R;import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewDebug; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo;/*** <p>* A button with two states, checked and unchecked. When the button is pressed* or clicked, the state changes automatically.* </p>** <p><strong>XML attributes</strong></p>* <p>* See {@link android.R.styleable#CompoundButton* CompoundButton Attributes}, {@link android.R.styleable#Button Button* Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link* android.R.styleable#View View Attributes}* </p>*/ public abstract class CompoundButton extends Button implements Checkable {private boolean mChecked;private int mButtonResource;private boolean mBroadcasting;private Drawable mButtonDrawable;private OnCheckedChangeListener mOnCheckedChangeListener;private OnCheckedChangeListener mOnCheckedChangeWidgetListener;private static final int[] CHECKED_STATE_SET = {R.attr.state_checked};public CompoundButton(Context context) {this(context, null);}public CompoundButton(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CompoundButton(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray a =context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0);Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);if (d != null) {setButtonDrawable(d);}boolean checked = a.getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false);setChecked(checked);a.recycle();}public void toggle() {setChecked(!mChecked);}@Overridepublic boolean performClick() {/** XXX: These are tiny, need some surrounding 'expanded touch area',* which will need to be implemented in Button if we only override* performClick()*//* When clicked, toggle the state */toggle();return super.performClick();}@ViewDebug.ExportedPropertypublic boolean isChecked() {return mChecked;}/*** <p>Changes the checked state of this button.</p>** @param checked true to check the button, false to uncheck it*/public void setChecked(boolean checked) {if (mChecked != checked) {mChecked = checked;refreshDrawableState();notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);// Avoid infinite recursions if setChecked() is called from a listenerif (mBroadcasting) {return;}mBroadcasting = true;if (mOnCheckedChangeListener != null) {mOnCheckedChangeListener.onCheckedChanged(this, mChecked);}if (mOnCheckedChangeWidgetListener != null) {mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);}mBroadcasting = false; }}/*** Register a callback to be invoked when the checked state of this button* changes.** @param listener the callback to call on checked state change*/public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {mOnCheckedChangeListener = listener;}/*** Register a callback to be invoked when the checked state of this button* changes. This callback is used for internal purpose only.** @param listener the callback to call on checked state change* @hide*/void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {mOnCheckedChangeWidgetListener = listener;}/*** Interface definition for a callback to be invoked when the checked state* of a compound button changed.*/public static interface OnCheckedChangeListener {/*** Called when the checked state of a compound button has changed.** @param buttonView The compound button view whose state has changed.* @param isChecked The new checked state of buttonView.*/void onCheckedChanged(CompoundButton buttonView, boolean isChecked);}/*** Set the background to a given Drawable, identified by its resource id.** @param resid the resource id of the drawable to use as the background */public void setButtonDrawable(int resid) {if (resid != 0 && resid == mButtonResource) {return;}mButtonResource = resid;Drawable d = null;if (mButtonResource != 0) {d = getResources().getDrawable(mButtonResource);}setButtonDrawable(d);}/*** Set the background to a given Drawable** @param d The Drawable to use as the background*/public void setButtonDrawable(Drawable d) {if (d != null) {if (mButtonDrawable != null) {mButtonDrawable.setCallback(null);unscheduleDrawable(mButtonDrawable);}d.setCallback(this);d.setVisible(getVisibility() == VISIBLE, false);mButtonDrawable = d;setMinHeight(mButtonDrawable.getIntrinsicHeight());}refreshDrawableState();}@Overridepublic void onInitializeAccessibilityEvent(AccessibilityEvent event) {super.onInitializeAccessibilityEvent(event);event.setClassName(CompoundButton.class.getName());event.setChecked(mChecked);}@Overridepublic void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {super.onInitializeAccessibilityNodeInfo(info);info.setClassName(CompoundButton.class.getName());info.setCheckable(true);info.setChecked(mChecked);}@Overridepublic int getCompoundPaddingLeft() {int padding = super.getCompoundPaddingLeft();if (!isLayoutRtl()) {final Drawable buttonDrawable = mButtonDrawable;if (buttonDrawable != null) {padding += buttonDrawable.getIntrinsicWidth();}}return padding;}@Overridepublic int getCompoundPaddingRight() {int padding = super.getCompoundPaddingRight();if (isLayoutRtl()) {final Drawable buttonDrawable = mButtonDrawable;if (buttonDrawable != null) {padding += buttonDrawable.getIntrinsicWidth();}}return padding;}/*** @hide*/@Overridepublic int getHorizontalOffsetForDrawables() {final Drawable buttonDrawable = mButtonDrawable;return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);final Drawable buttonDrawable = mButtonDrawable;if (buttonDrawable != null) {final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;final int drawableHeight = buttonDrawable.getIntrinsicHeight();final int drawableWidth = buttonDrawable.getIntrinsicWidth();int top = 0;switch (verticalGravity) {case Gravity.BOTTOM:top = getHeight() - drawableHeight;break;case Gravity.CENTER_VERTICAL:top = (getHeight() - drawableHeight) / 2;break;}int bottom = top + drawableHeight;int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;int right = isLayoutRtl() ? getWidth() : drawableWidth;buttonDrawable.setBounds(left, top, right, bottom);buttonDrawable.draw(canvas);}}@Overrideprotected int[] onCreateDrawableState(int extraSpace) {final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);if (isChecked()) {mergeDrawableStates(drawableState, CHECKED_STATE_SET);}return drawableState;}@Overrideprotected void drawableStateChanged() {super.drawableStateChanged();if (mButtonDrawable != null) {int[] myDrawableState = getDrawableState();// Set the state of the DrawablemButtonDrawable.setState(myDrawableState);invalidate();}}@Overrideprotected boolean verifyDrawable(Drawable who) {return super.verifyDrawable(who) || who == mButtonDrawable;}@Overridepublic void jumpDrawablesToCurrentState() {super.jumpDrawablesToCurrentState();if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState();}static class SavedState extends BaseSavedState {boolean checked;/*** Constructor called from {@link CompoundButton#onSaveInstanceState()}*/SavedState(Parcelable superState) {super(superState);}/*** Constructor called from {@link #CREATOR}*/private SavedState(Parcel in) {super(in);checked = (Boolean)in.readValue(null);}@Overridepublic void writeToParcel(Parcel out, int flags) {super.writeToParcel(out, flags);out.writeValue(checked);}@Overridepublic String toString() {return "CompoundButton.SavedState{"+ Integer.toHexString(System.identityHashCode(this))+ " checked=" + checked + "}";}public static final Parcelable.Creator<SavedState> CREATOR= new Parcelable.Creator<SavedState>() {public SavedState createFromParcel(Parcel in) {return new SavedState(in);}public SavedState[] newArray(int size) {return new SavedState[size];}};}@Overridepublic Parcelable onSaveInstanceState() {// Force our ancestor class to save its statesetFreezesText(true);Parcelable superState = super.onSaveInstanceState();SavedState ss = new SavedState(superState);ss.checked = isChecked();return ss;}@Overridepublic void onRestoreInstanceState(Parcelable state) {SavedState ss = (SavedState) state;super.onRestoreInstanceState(ss.getSuperState());setChecked(ss.checked);requestLayout();} }

總結(jié)

以上是生活随笔為你收集整理的Android中CheckBox与CompoundButton源码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。