Android自定义view仿IOS开关效果

下面我将为您详细讲解“Android自定义view仿IOS开关效果”的完整攻略。

简介

本文将介绍如何实现一个仿IOS开关的自定义View,当然,这种开关在Android中早已有其它的替代品,但是通过手动编写开关的代码,了解自定义View的知识,在此基础上进行风格的定制以及不同需求的实现,这是值得一学的。

实现思路

开关主要由背景圆角矩形、白色小球、阴影三部分组成,具体步骤如下:

  1. 编写自定义View,继承View类。

  2. 在onMeasure()方法中计算View宽高大小。

  3. 在onDraw()方法中画出开关的三个部分。

  4. 在onTouchEvent()方法中监听手势事件,移动白色小球,并刷新View。

  5. 在performClick()方法中发生点击事件。

代码实现

定义View

首先定义一个CustomSwitchView类,继承View类。

public class CustomSwitchView extends View {
    private final String TAG = CustomSwitchView.class.getSimpleName();
    // 自定义View的宽度和高度
    private int mWidth = 150, mHeight = 70;
    // 默认为关闭状态
    private boolean mIsOn = false;
    // 开关的背景颜色
    private int mBackgroundColor = Color.parseColor("#CCCCCC");
    // 开关的圆角半径
    private float mRadius = 35;
    // 开关白色按钮的半径
    private float mButtonRadius = mHeight / 2 - 5;
    // 开关白色按钮的水平坐标
    private float mButtonX;
    // 开关白色按钮的最左边和最右边的坐标,用于限制按钮的移动范围
    private float mButtonLeft, mButtonRight;
    // 开关的状态改变事件监听器
    private OnSwitchStateChangedListener mOnSwitchStateChangedListener;

    public CustomSwitchView(Context context) {
        super(context);
    }

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

    public CustomSwitchView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    // 初始化方法,计算一些参数值
    private void init() {
        mWidth = getWidth();
        mHeight = getHeight();
        mRadius = mHeight / 2;
        mButtonRadius = mHeight / 2 - 5;
        mButtonLeft = mButtonRadius + 5;
        mButtonRight = mWidth - mButtonRadius - 5;
        mButtonX = mIsOn ? mButtonRight : mButtonLeft;
    }

    // 绘制View图形
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        init();

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setAntiAlias(true);

        // 画背景和阴影
        RectF rect = new RectF(0, 0, mWidth, mHeight);
        paint.setColor(mBackgroundColor);
        paint.setShadowLayer(3f, 3f, 3f, 0x7f000000);
        canvas.drawRoundRect(rect, mRadius, mRadius, paint);

        // 画开关白色按钮
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mButtonX, mRadius, mButtonRadius, paint);
    }

    // 重写onTouchEvent方法来监听手势事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                performClick();
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                if (x < mButtonLeft) {
                    mButtonX = mButtonLeft;
                } else if (x > mButtonRight) {
                    mButtonX = mButtonRight;
                } else {
                    mButtonX = x;
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                float center = (mButtonLeft + mButtonRight) / 2;
                if (mButtonX >= center) {
                    mButtonX = mButtonRight;
                } else {
                    mButtonX = mButtonLeft;
                }
                mIsOn = (mButtonX == mButtonRight);
                if (mOnSwitchStateChangedListener != null) {
                    mOnSwitchStateChangedListener.onStateChanged(mIsOn);
                }
                invalidate();
                break;
            default:
        }
        return true;
    }

    // 重写performClick方法,发生点击事件
    @Override
    public boolean performClick() {
        super.performClick();
        return true;
    }

    // 设置开关的状态改变事件监听器
    public void setOnSwitchStateChangedListener(OnSwitchStateChangedListener listener) {
        this.mOnSwitchStateChangedListener = listener;
    }

    // 开关状态改变事件监听器
    public interface OnSwitchStateChangedListener {
        void onStateChanged(boolean isOn);
    }
}

在xml布局文件中使用View

在xml布局文件中使用自定义控件,设置控件的宽高大小即可:

<com.xxx.xxx.CustomSwitchView
    android:id="@+id/switchView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:layout_gravity="center_horizontal"
    />

监听开关状态改变事件

我们可以通过实现OnSwitchStateChangedListener接口,监听开关状态的改变事件。

CustomSwitchView switchView = findViewById(R.id.switchView);
switchView.setOnSwitchStateChangedListener(new CustomSwitchView.OnSwitchStateChangedListener() {
    @Override
    public void onStateChanged(boolean isOn) {
        if (isOn) {
            // 开关打开
        } else {
            // 开关关闭
        }
    }
});

示例说明

示例一:修改开关背景颜色

在CustomSwitchView类中定义一个setBackgroundColor()方法,允许外部修改开关的背景颜色。

public void setBackgroundColor(int color) {
    mBackgroundColor = color;
    invalidate();
}

在Activity中通过调用switchView.setBackgroundColor()方法修改开关背景颜色。

CustomSwitchView switchView = findViewById(R.id.switchView);
switchView.setBackgroundColor(Color.parseColor("#FF4081")); // 修改背景色为深粉色

示例二:修改开关初始化状态

在CustomSwitchView类中定义一个setSwitchStatus()方法,允许外部修改开关的初始化状态。

public void setSwitchStatus(boolean isOn) {
    mIsOn = isOn;
    mButtonX = mIsOn ? mButtonRight : mButtonLeft;
    invalidate();
}

在Activity中通过调用switchView.setSwitchStatus()方法修改开关的初始化状态。

CustomSwitchView switchView = findViewById(R.id.switchView);
switchView.setSwitchStatus(true); // 初始状态为开启

总结

在本文中,我们实现了一个仿IOS开关的自定义View。通过手写代码实现一个比较简单的自定义View是值得推荐的一种学习方式。

完整代码请见github项目:https://github.com/wanglu1209/CustomSwitchView

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android自定义view仿IOS开关效果 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Win11右键上下文菜单存在BUG 微软将着手进行修复

    Win11右键上下文菜单存在BUG 最近Win11的用户反映了一个问题,就是在某些情况下右键菜单会出现异常,如菜单项重复、图标错误等。经过微软的证实,这确实是Win11系统的一个BUG。 修复方法 目前微软正在积极开展修复工作,预计最新的更新会在近日内发布。用户可以及时更新系统补丁来解决这个问题。 另外,为了避免这个问题再次出现,用户也可以尝试以下的一些方法…

    other 2023年6月27日
    00
  • php使用变量动态创建类的对象用法示例

    PHP使用变量动态创建类的对象用法示例 示例1:使用变量创建对象 $class = ‘MyClass’; $obj = new $class(); 在上述示例中,我们使用变量$class来存储类名,并通过new $class()的方式创建了一个对象。 示例2:使用变量创建带参数的对象 $class = ‘MyClass’; $arg1 = ‘value1’;…

    other 2023年10月14日
    00
  • 五个经典链表OJ题带你进阶C++链表篇

    五个经典链表OJ题带你进阶C++链表篇 前言 链表作为一种非常重要的数据结构,常常用来解决一些实际问题。在代码中,我们需要用到链表时,不能只是会使用,而是要掌握它的一些经典问题,才能真正了解链表的一些相关性质和应用。本篇攻略介绍了五个经典的链表OJ题,通过解析这些问题,帮助初学者进阶学习C++链表。 问题一:求链表的长度 输入一个单链表,输出链表的长度。 算…

    other 2023年6月27日
    00
  • go语言中匿名函数的作用域陷阱详解

    Go语言中匿名函数的作用域陷阱详解 在Go语言中,匿名函数是一种没有函数名的函数,可以在其他函数内部定义和使用。匿名函数的作用域和变量捕获机制可能会导致一些陷阱,需要注意。 作用域陷阱 当在匿名函数内部引用外部变量时,需要注意变量的作用域。匿名函数可以访问外部函数的局部变量,但是在匿名函数内部修改这些变量的值可能会导致意外的结果。 示例1: package …

    other 2023年8月15日
    00
  • pythonlist转json

    当然,我很乐意为您提供有关“Python List转JSON”的完整攻略。以下是详细的步骤和两个示例: 1. 什么是JSON? JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。它基于JavaScript语言的一个子集,但是可以被多种编语言使用,包括Python。 2. Python List转JSO…

    other 2023年5月6日
    00
  • JavaScript判断浏览器版本的方法

    JavaScript判断浏览器版本的方法 在JavaScript中,我们可以使用不同的方法来判断用户所使用的浏览器版本。下面是一些常用的方法: 1. 使用navigator.userAgent属性 navigator.userAgent属性返回浏览器的用户代理字符串,其中包含了浏览器的相关信息,包括版本号。我们可以通过解析这个字符串来获取浏览器的版本信息。 …

    other 2023年8月3日
    00
  • PostgreSQL 修改表字段常用命令操作

    下面是关于“PostgreSQL 修改表字段常用命令操作”的完整攻略: 1. 修改表字段数据类型 当需要修改表字段数据类型时,可以使用以下命令: ALTER TABLE table_name ALTER COLUMN column_name SET DATA TYPE new_data_type; 其中,table_name 为要修改的表名,column_n…

    other 2023年6月25日
    00
  • 6个优秀的微信小程序ui组件库

    以下是详细讲解“6个优秀的微信小程序UI组件库的完整攻略”的标准Markdown格式文本: 6个优秀的微信小程序UI组件库 微信小程序是一种轻量级的应用程序,可以在微信中运行。为了更好地展示小程序的内容,开发人员可以使用UI组件库来创建漂亮的用户界面。本攻略将介绍6个优秀的微信小程序UI组件库,包括其特点、使用方法和示例说明等内容。 1. WeUI WeUI…

    other 2023年5月10日
    00
合作推广
合作推广
分享本页
返回顶部