Switch实现原理分析

Switch 控件是 Android 中用来表示开关状态的一个 UI 元素,它继承自 CompoundButton,这意味着它也继承了 Button 的一些特性,比如事件处理等。Switch 控件主要用于二进制选择,即开和关两种状态。下面我将结合源码分析 Switch 的实现原理。

1. Switch 类定义

Switch 类定义如下:

1public class Switch extends CompoundButton {
2    // ...
3}

2. 构造函数

Switch 的构造函数如下:

1public Switch(Context context) {
2    this(context, null);
3}
4
5public Switch(Context context, AttributeSet attrs) {
6    this(context, attrs, android.R.attr.switchStyle);
7}
8
9public Switch(Context context, AttributeSet attrs, int defStyleAttr) {
10    super(context, attrs, defStyleAttr);
11    initSwitch();
12}

构造函数中调用了 initSwitch 方法来初始化 Switch 的属性。

3. 初始化

初始化方法会设置默认属性,并读取自定义属性。

1void initSwitch() {
2    // ...
3    TypedArray a = getContext().obtainStyledAttributes(
4        mAttrs, R.styleable.Switch, mDefStyleAttr, 0);
5
6    // ...
7    // 读取样式属性
8    mThumbDrawable = a.getDrawable(R.styleable.Switch_thumb);
9    mTrackDrawable = a.getDrawable(R.styleable.Switch_track);
10    // ...
11
12    a.recycle();
13
14    // 初始化文本和图标
15    initCompoundButton();
16
17    // 设置默认的触摸反馈效果
18    setTouchFeedbackColorResource(android.R.color.holo_blue_bright);
19    // ...
20}

这里可以看到 Switch 通过 TypedArray 获取了自定义的样式属性,如 thumbtrack 图标。

4. 状态变化

Switch 可以通过 setChecked 方法来改变开关状态。

1public void setChecked(boolean checked) {
2    if (checked != mChecked) {
3        mChecked = checked;
4        refreshDrawableState();
5        if (!mPressed) {
6            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
7        }
8        performClick();
9    }
10}

5. 状态集

Switch 使用状态集来管理不同的状态下的外观。

1@Override
2protected int[] onCreateDrawableState(int extraSpace) {
3    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
4    if (isChecked()) {
5        mergeDrawableStates(drawableState, CHECKED_STATE_SET);
6    }
7    if (isPressed()) {
8        mergeDrawableStates(drawableState, PRESSED_STATE_SET);
9    }
10    return drawableState;
11}

6. 绘制

Switch 重写了 onDraw 方法来绘制文本和图标。

1@Override
2protected void onDraw(Canvas canvas) {
3    super.onDraw(canvas);
4    // ...
5    // 绘制 track 和 thumb
6    if (mTrackDrawable != null) {
7        mTrackDrawable.setBounds(mTrackRect);
8        mTrackDrawable.draw(canvas);
9    }
10
11    if (mThumbDrawable != null) {
12        mThumbDrawable.setBounds(mThumbRect);
13        mThumbDrawable.draw(canvas);
14    }
15    // ...
16}

7. 计算 thumb 和 track 的位置

Switch 需要计算 thumb 和 track 的位置以便正确地显示。

1void computeThumbPosition() {
2    final int trackWidth = mTrackRect.width();
3    final int thumbHalfWidth = mThumbRect.width() / 2;
4
5    if (trackWidth > 0 && thumbHalfWidth > 0) {
6        final int thumbPos = (trackWidth - thumbHalfWidth) * mThumbOffset + thumbHalfWidth;
7        mThumbRect.offset(mTrackRect.left + thumbPos, mTrackRect.top);
8    }
9}

8. 事件处理

Switch 通过处理点击事件来改变开关状态。

1@Override
2public boolean performClick() {
3    toggle();
4    playSoundEffect(SoundEffectConstants.CLICK);
5    return super.performClick();
6}
7
8public void toggle() {
9    setChecked(!mChecked);
10}

9. 焦点和触摸事件

Switch 通过处理焦点变化和触摸事件来更新其状态。

1@Override
2public boolean onHoverEvent(MotionEvent event) {
3    // ...
4    return super.onHoverEvent(event);
5}
6
7@Override
8public boolean onTouchEvent(MotionEvent event) {
9    // ...
10    return super.onTouchEvent(event);
11}

10. 适配器模式

Switch 通过 CompoundButton 实现了适配器模式,允许同时处理文本和图标。

1public abstract class CompoundButton extends Button implements CompoundButton.OnCheckedChangeListener {
2    // ...
3}

11. 事件监听器

Switch 支持通过 OnCheckedChangeListener 监听选中状态的变化。

1public static abstract class OnCheckedChangeListener implements BaseAdapter.DataSetObserver {
2    // ...
3}
4
5public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
6    mOnCheckedChangeListener = listener;
7}
8
9@Override
10public void performClick() {
11    // ...
12    if (mOnCheckedChangeListener != null) {
13        mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
14    }
15    // ...
16}

12. 样式和主题

Switch 支持通过 XML 属性来自定义样式。

1<Switch
2    android:id="@+id/switch"
3    android:layout_width="wrap_content"
4    android:layout_height="wrap_content"
5    android:textOn="On"
6    android:textOff="Off"
7    android:checked="true"
8    android:track="@drawable/switch_track"
9    android:thumb="@drawable/switch_thumb" />

总结

Switch 控件的核心在于两个主要的图形元素:track(轨道)和 thumb(滑块)。当状态改变时,thumb 的位置也会相应改变,从而模拟开关的效果。Switch 还提供了对触摸事件的支持以及事件监听器来响应状态的变化。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值