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

Android中的自定义checkable是指用户可以选择或取消选择的视图。通常,我们可以使用CheckBox或RadioButton来实现checkable效果,但有时我们需要自定义自己的checkable视图。 为了实现自定义checkable,我们需要遵循以下步骤: 1. 创建自定义视图类。我们可以创建一个继承自ViewViewGroup的类来定义我们自己的可选择视图。我们可以使用自定义属性来指定视图的外观和行为。 2. 实现OnCheckedChangeListener接口。这个接口定义了当用户选择或取消选择视图时应该执行的操作。我们可以在自定义视图类中实现这个接口,并根据需要执行相应的操作。 3. 添加状态切换逻辑。当用户选择或取消选择视图时,我们需要在自定义视图类中实现适当的状态切换逻辑。我们可以通过设置视图的背景、文本颜色等来反映视图的选择状态。 4. 处理点击事件。当用户点击自定义视图时,我们需要根据当前的选择状态来决定是否要切换到另一种状态。我们可以在自定义视图类中实现OnClickListener接口,并在onClick()方法中处理点击事件。 5. 通过属性设置可选择性。我们可以定义一个自定义属性来指定视图是否可选择。这个属性可以是一个布尔值,通过在布局文件中设置该属性,我们可以确定视图的初始选择状态。 通过以上步骤,我们就可以实现一个自定义的checkable视图。使用自定义checkable视图可以增加我们的应用程序的灵活性和可扩展性,使我们能够创建更多样化和个性化的用户界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值