Android实现类似ios滑动按钮
作者:番茄炒蛋不要蛋 发布时间:2023-06-26 11:17:48
标签:Android,ios,滑动按钮
IOS的滑动按钮菜单在UI设计里面绝对堪称一绝,在学习了Android的自定义view后,我萌生了模仿它的想法。
实现上面的模拟需要自定义一个View;
1)、在View的OnDraw里画出圆角矩形,分别为灰色圆角矩形,红色圆角矩形,和绿色圆角矩形。然后计算相应的位置。
2)、本例中的宽高比为1:0.65,内部红色矩形尺寸为外部矩形尺寸0.9,内部的圆的半径为外部高的0.45倍。按照这个比例计算相应的坐标。
3)、本例中的动画是用ValueAnimation实现的,具体实现在下部代码中。
4)、本例中的透明度实现方法和运动动画一样。
5)、自定义View为外部提供了读取和修改内部状态的接口。
具体代码如下,
1、界面的XML代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_switch_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.app_switchbutton.SwitchButtonActivity">
<com.example.app_switchbutton.switchbutton
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true" />
<com.example.app_switchbutton.switchbutton
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
2、实现自定义view的java代码:
package com.example.app_switchbutton;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RadioButton;
/**
* Created by 尽途 on 2017/4/26.
*/
public class switchbutton extends View {
private int widthSize;
private int heightSize;
private boolean isOn=false;
private float WhiteRoundRect_width,WhiteRoundRect_height;
private float Circle_X,Circle_Y,WhiteRoundRect_X,WhiteRoundRect_Y;
private float Radius;
private float currentValue;
private int currentAlphaofGreen,currentAlphaofGray;
public switchbutton(Context context){
super(context);
}
public switchbutton(Context context, AttributeSet attributeSet){
super(context,attributeSet);
setLayerType(LAYER_TYPE_SOFTWARE,null);
initData();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
widthSize=MeasureSpec.getSize(widthMeasureSpec);
heightSize=(int)(widthSize*0.65f);
setMeasuredDimension(widthSize,heightSize);
initData();
}
void initData(){
if (isOn){
currentValue=widthSize-0.5f*heightSize;
currentAlphaofGreen=255;
currentAlphaofGray=0;
}
else {
currentValue=0.5f*heightSize;
currentAlphaofGreen=0;
currentAlphaofGray=255;
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isOn){
DrawBackGreenRoundRect(canvas);
DrawCircle(canvas);
}
else {
DrawBackGrayRoundRect(canvas);
DrawBackWhiteRoundRect(canvas);
DrawCircle(canvas);
}
}
private void DrawBackGrayRoundRect(Canvas canvas){
Paint paint0=new Paint();
paint0.setStyle(Paint.Style.FILL);
paint0.setColor(Color.GRAY);
paint0.setAntiAlias(true);
paint0.setAlpha(currentAlphaofGray);
RectF roundRect=new RectF(0,0,widthSize,heightSize);
canvas.drawRoundRect(roundRect,heightSize*0.5f,heightSize*0.5f,paint0);
}
private void DrawBackGreenRoundRect(Canvas canvas){
Paint paint1=new Paint();
paint1.setStyle(Paint.Style.FILL);
paint1.setColor(Color.GREEN);
paint1.setAntiAlias(true);
paint1.setAlpha(currentAlphaofGreen);
RectF roundRect=new RectF(0,0,widthSize,heightSize);
canvas.drawRoundRect(roundRect,heightSize*0.5f,heightSize*0.5f,paint1);
}
private void DrawCircle(Canvas canvas){
Circle_Y=heightSize*0.5f;
Radius=heightSize*0.45f;
Paint paint2=new Paint();
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(Color.WHITE);
paint2.setAntiAlias(true);
canvas.drawCircle(currentValue,Circle_Y,Radius,paint2);
}
private void DrawBackWhiteRoundRect(Canvas canvas){
Paint paint3=new Paint();
paint3.setStyle(Paint.Style.FILL);
paint3.setColor(Color.RED);
paint3.setAntiAlias(true);
paint3.setAlpha(currentAlphaofGray);
WhiteRoundRect_X=heightSize*0.05f;
WhiteRoundRect_Y=heightSize*0.05f;
WhiteRoundRect_width=widthSize-0.05f*heightSize;
WhiteRoundRect_height=heightSize*0.95f;
RectF rectf=new RectF(WhiteRoundRect_X,WhiteRoundRect_Y,WhiteRoundRect_width,WhiteRoundRect_height);
canvas.drawRoundRect(rectf,WhiteRoundRect_height*0.5f,WhiteRoundRect_height*0.5f,paint3);
}
/**
* 添加了过渡值动画,实现了平缓运动
* @param startValue
* @param endValue
*/
private void setAnimation(float startValue,float endValue){
ValueAnimator valueAnimator=ValueAnimator.ofFloat(startValue,endValue);
valueAnimator.setDuration(1500);
valueAnimator.setTarget(currentValue);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentValue=(float)animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
private void setAlphaAnimationofGray(int startValue,int endValue){
ValueAnimator valueAnimator=ValueAnimator.ofInt(startValue,endValue);
valueAnimator.setDuration(1500);
valueAnimator.setTarget(currentAlphaofGray);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAlphaofGray=(int)animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
private void setAlphaAnimationofGreen(int startValue,int endValue){
ValueAnimator valueAnimator=ValueAnimator.ofInt(startValue,endValue);
valueAnimator.setDuration(1500);
valueAnimator.setTarget(currentAlphaofGreen);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAlphaofGreen=(int)animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
return false;
case MotionEvent.ACTION_UP:
isOn=!isOn;
invalidate();
break;
default:
break;
}
if (isOn){
float startCircle_X=0.5f*heightSize;
float endCircle_X=widthSize-0.5f*heightSize;
setAnimation(startCircle_X,endCircle_X);
setAlphaAnimationofGray(255,0);
setAlphaAnimationofGreen(0,255);
}else {
float startCircle_X=widthSize-0.5f*heightSize;
float endCircle_X=heightSize*0.5f;
setAnimation(startCircle_X,endCircle_X);
setAlphaAnimationofGray(0,255);
setAlphaAnimationofGreen(255,0);
}
return super.onTouchEvent(event);
}
public void writeSwitchButtonState(boolean isOn){
this.isOn=isOn;
}
public boolean readSwitchButtonState(){
return isOn;
}
}
模仿的不是很到位,请大家见谅。
来源:https://blog.csdn.net/ZQL2288/article/details/70941131


猜你喜欢
- BeanPostProcessor接口作用:如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处
- MainApplication类文件的位置搭建 SpringBoot 项目时有一个主程序入口类.这个 MainApp 类必须在放在整个项目的
- 在Web开发过程中离不开数据的交互,这就需要规定交互数据的相关格式,以便数据在客户端与服务器之间进行传递。数据的格式通常有2种:1、xml;
- 一、User Agent的含义User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及
- 线程线程:对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务。一个进程的多
- 1、首先说一下用法,BigDecimal中的divide主要就是用来做除法的运算。其中有这么一个方法.public BigDecimal d
- SpringBoot小白创建项目,扫描不到Controller一系列问题1.2.3.4.5.6.还有一种办法是在启动服务类的入门,添加@Co
- 本文实例讲述了Android编程实现自定义手势的方法。分享给大家供大家参考,具体如下:之前介绍过如何在Android程序中使用手势,主要是系
- 序章简介:bean的加载控制指根据特定情况对bean进行选择性加载以达到适用项目的目标。根据之前对bean加载的八种方式,其中后面四种是可以
- 本文实例讲述了C#数据结构之双向链表(DbLinkList)。分享给大家供大家参考,具体如下:这是继上一篇《C#数据结构之单链表(LinkL
- SWF Tools 是一组用来处理 Flash 的 swf 文件的工具包,包括:1. 合并工具 swfcombine2. 抽取工具 swfe
- C#串口模块的使用。使用VS .net框架下WinForm程序应用开发。C#开发的串口通信小工具。相比于QT添加的串口类,WinForm是通
- 本文实例为大家分享了Android检测手机多点触摸点数的具体代码,供大家参考,具体内容如下说明:手指每点击一个地方,在那个地方就画一个圆第一
- 一对多查询一对多关联查询是指在查询一方对象的时候,同时将其所关联的多方对象也都查询出来。下面以班级 Classes 与学生 Student
- 一、Mybatis执行流程具体分析Mybatis是如何操作数据库的!1、定义我们的核心配置文件的路径,这个路径是从target/classe
- 1. 前言Spring的核心技术IOC(Intorol of Converse控制反转)的实现途径是DI(dependency Insert
- 先说能用的究极解决方案,大家着急的直接复制走,以后想了解再过来看没有header,且所有Item的高度一致private fun getSc
- 源程序揭秘杨辉三角形性质: 每行数字左右对称,由 1 开始逐渐变大,然后变小,回到 1。 第 n 行的数字个数为 n 个。 第 n 行数字和
- 目录前言一 安全性问题1.1 调用接口的先决条件-token1.2 使用POST作为接口请求方式1.3 客户端IP白名单1.4 单个接口针对
- 使用RedisTemplate根据前缀获取key列表我们在使用 Redis 的时候,会需要获取以某个字符串开头的所有 key批量获取 key