热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android实现类似ios滑动按钮

这篇文章主要为大家详细介绍了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代码:

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
  
  
 

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;
  }
}

模仿的不是很到位,请大家见谅。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
author-avatar
晓志1998_809
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有