Checkable Views

drawable state系列文章
XML类型的drawable图片的解析处理过程

StateListDrawable使用详解

详解refreshDrawableList()的执行流程

Checkable Views

Android中自定义drawable states

===============================================

一、什么是Checkable?

Checkable是一个接口,如果你自定义的View需要在是与否之间改变其状态,那么你就可以实现这个接口,在Android框架中也包含了一些View实现了这个接口,例如:CheckedTextView和CompounButton就是其中最主要的两个,另外也有它们的一些子类你可以使用,例如:Checkbox, RadioButton, Switch和ToggleButton.

这些View是非常有用的,但是如果你需要一些更复杂功能该怎么办?那么你就需要自己去实现它了。

Checkable源码如下;

/*
 * 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;

/**
 * Defines an extension for views that make them checkable.
 *
 */
public interface Checkable {

    /**
     * Change the checked state of the view
     * 
     * @param checked The new checked state
     */
    void setChecked(boolean checked);

    /**
     * @return The current checked state of the view
     */
    boolean isChecked();

    /**
     * Change the checked state of the view to the inverse of its current state
     *
     */
    void toggle();
}

二、CheckableLinearLayout

CheckableLinearLayout是一个可以取代LinearLayout的类,并且它对Checkable接口也提供了支持.网上有很多这个类的实现,但是很多都忽略了触发背景图片改变状态的功能。

public void setChecked(boolean b) {
    // cut down version of method
    // ...

    refreshDrawableState();

    if (mOnCheckedChangeListener != null) {
        mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
    }
}

// MAOR CODE

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

可以看到,我也在上面添加了一个OnCheckedChangedListener,它将让你很容易在选择状态改变的时候进行相应的操作。

三、如果我不想使用LinearLayout该怎么办?

最简单的方法就是从继承的子View来改变它所继承的父类,需要注意的是这也要改变类名。

四、获取子View的状态改变

假设有一个布局,一个CheckableLinearLayout作为父控件,一个Checkbox作为子控件,这是你使用ListView的CHOICE_MODE_MULTIPLE模式的一个普遍的场景。如果Checkbox是可点击的,并且点击将引起状态开关的改变,但是你也可能希望父类的状态也能引起这个状态开关的改变。你可能会手工的加上一个listener,但是更容易的是设置ViewGroup的addStatesFromChildren的属性。
通过设置这个属性为true,ViewGroup将复制子View的状态,下面的例子将告诉你怎样使用这个布局,你也可以调用setAddStatesFromChildren(boolean)这个方法。

<?xml version="1.0" encoding="utf-8">
<com.example.checkableviews.CheckableLinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="?android:attr/listPreferredItemHeight"
  android:addStatesFromChildren="true"         
  android:background="@drawable/checked_background">

    <CheckBox android:layout_height="wrap_content"
              android:layout_width="wrap_content" />

</com.example.checkableviews.CheckableLinearLayout>

CheckableLinearLayout类完整的代码

package com.example.checkableviews;

/*******************************************************************************
 * Copyright 2013 Chris Banes.
 *
 * 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.    
 *******************************************************************************/

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class CheckableLinearLayout extends LinearLayout implements Checkable {

    /**
     * Interface definition for a callback to be invoked when the checked state of this View is
     * changed.
     */
    public static interface OnCheckedChangeListener {

        /**
         * Called when the checked state of a compound button has changed.
         *
         * @param checkableView The view whose state has changed.
         * @param isChecked     The new checked state of checkableView.
         */
        void onCheckedChanged(View checkableView, boolean isChecked);
    }

    private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};

    private boolean mChecked = false;

    private OnCheckedChangeListener mOnCheckedChangeListener;

    public CheckableLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public boolean isChecked() {
        return mChecked;
    }

    public void setChecked(boolean b) {
        if (b != mChecked) {
            mChecked = b;
            refreshDrawableState();

            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
            }
        }
    }

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

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

    /**
     * Register a callback to be invoked when the checked state of this view changes.
     *
     * @param listener the callback to call on checked state change
     */
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeListener = listener;
    }

}

原文链接:

Checkable Views

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值