Android实现长按圆环动画View效果的思路代码

一、需求来源

最近想到一个需求,类似悦跑圈或者Keep的结束按钮动画


二、思路代码

该动画按钮的主要作用就是防止用户误操作,具体实现思路如下:
1、监听用户的触摸事件OnTouchListener,在ACTION_DOWN的时候,记录下xy坐标和触摸时间,同时start自定义View动画;在ACTION_MOVE的过程中,判断坐标差值的偏移量是否在一个可接受的范围内,是的话就保留当前动画,不是的话就清除按钮上绘制的path;在ACTION_UP的时候,再次记录下触摸时间,比较两个时间是否达到了长按规定的时间,是的话就执行下一个事件,不是的话就停止动画重置Path。

val touchMax = 50
    var lastX = 0
    var lastY = 0
    circleView.setOnTouchListener(object : View.OnTouchListener{
      override fun onTouch(p0: View?, motionEvent: MotionEvent): Boolean {
        val endTime: Long
        val x = motionEvent.x
        val y = motionEvent.y
        when (motionEvent.action) {
          MotionEvent.ACTION_DOWN -> {
            startTime = System.currentTimeMillis()
            lastX = x.toInt()
            lastY = y.toInt()
            circleView.startAnim()
          }
          MotionEvent.ACTION_UP -> {
            endTime = System.currentTimeMillis()
            val during = endTime - startTime
            if (during < App.LONG_CLICK_TIME) {
              circleView.cancelAnim()
              circleView.clearAll()
            }else{
              playMaxWarn()
            }
          }
          MotionEvent.ACTION_MOVE -> {
            if (abs(lastX - x) > touchMax || abs(lastY - y) > touchMax) {
              circleView.clearAll()
            }
          }
        }
        return false
      }
    })

2、就是在自定义View里arcTo画一个圆,再使用属性动画来监听动画的播放即可

fun startAnim() {
    isClear = false
    valueAnimator = ValueAnimator.ofFloat(0F, 359.9999F)
    valueAnimator!!.duration = App.LONG_CLICK_TIME
    valueAnimator!!.addUpdateListener { animation ->
      mProgress = animation.animatedValue as Float
      invalidate()
    }
    valueAnimator!!.start()
  }

三、效果展示

最终实现效果图虽然没有上面那么好看,但基本效果还是达到了

四、全部代码

package cn.xmliu.melongo.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import cn.xmliu.melongo.App
import cn.xmliu.melongo.R

/**
 * Date: 2020/8/12 13:21
 * Email: diyangxia@163.com
 * Description: 长按动画View
 */
class LongCircleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {

  /**
   * 画笔
   */
  private val paint = Paint()
  private var arcPath: Path? = null
  private var rectF: RectF? = null
  private var lineColor = 0

  /**
   * 中心点坐标、半径
   */
  private var centerX: Float? = null
  private var centerY: Float? = null
  private var radius: Float? = null

  private var left = -1F
  private var top = -1F
  private var right = -1F
  private var bottom = -1F
  private val offset = 10

  private var mProgress = -1F
  private var valueAnimator: ValueAnimator ?= null
  private var isClear = true

  init {
    lineColor = ContextCompat.getColor(context!!, R.color.red)

  }

  override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    centerX = width / 2.toFloat()
    centerY = height / 2.toFloat()
    radius = height / 2.toFloat()
    left = centerX!! - radius!! + offset
    top = centerY!! - radius!! + offset
    right = centerX!! + radius!! - offset
    bottom = centerY!! + radius!! - offset

    rectF = RectF(left, top, right, bottom)
    arcPath = Path()
  }

  override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    paint.isAntiAlias = true
    paint.color = lineColor
    paint.style = Paint.Style.STROKE
    paint.strokeWidth = 10F
    arcPath!!.rewind() // 清除直线数据,保留数据结构,方便快速重用
    if(isClear) return
    arcPath!!.arcTo(rectF!!, 270F, mProgress)
    canvas?.drawPath(arcPath!!, paint)
  }

  fun startAnim() {
    isClear = false
    valueAnimator = ValueAnimator.ofFloat(0F, 359.9999F)
    valueAnimator!!.duration = App.LONG_CLICK_TIME
    valueAnimator!!.addUpdateListener { animation ->
      mProgress = animation.animatedValue as Float
      invalidate()
    }
    valueAnimator!!.start()
  }

  fun cancelAnim(){
    valueAnimator!!.cancel()
  }

  fun clearAll() {
    isClear = true
    invalidate()
  }
}
<RelativeLayout
        android:layout_width="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_height="wrap_content">

        <LinearLayout
          android:id="@+id/flashLayout"
          android:layout_centerInParent="true"
          android:layout_width="70dp"
          android:layout_height="70dp"
          android:background="@drawable/btn_circle_white"
          android:gravity="center_horizontal"
          android:orientation="vertical">

          <ImageView
            android:id="@+id/flashIV"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:padding="7dp"
            android:src="@drawable/menu_flash_black"
            android:text="闪灯开"
            android:tint="@color/main_color" />

          <TextView
            android:id="@+id/flashTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="闪灯"
            android:textColor="@color/main_color" />
        </LinearLayout>

        <cn.xmliu.melongo.view.LongCircleView
          android:id="@+id/circleView"
          android:layout_width="80dp"
          android:layout_height="80dp" />
      </RelativeLayout>
val touchMax = 50
    var lastX = 0
    var lastY = 0
    circleView.setOnTouchListener(object : View.OnTouchListener{
      override fun onTouch(p0: View?, motionEvent: MotionEvent): Boolean {
        val endTime: Long
        val x = motionEvent.x
        val y = motionEvent.y
        when (motionEvent.action) {
          MotionEvent.ACTION_DOWN -> {
            startTime = System.currentTimeMillis()
            lastX = x.toInt()
            lastY = y.toInt()
            circleView.startAnim()
          }
          MotionEvent.ACTION_UP -> {
            endTime = System.currentTimeMillis()
            val during = endTime - startTime
            if (during < App.LONG_CLICK_TIME) {
              circleView.cancelAnim()
              circleView.clearAll()
            }else{
              flashTV.text = "OK"
            }
          }
          MotionEvent.ACTION_MOVE -> {
            if (abs(lastX - x) > touchMax || abs(lastY - y) > touchMax) {
              circleView.clearAll()
            }
          }
        }
        return false
      }
    })

总结

到此这篇关于Android实现长按圆环动画View效果的文章就介绍到这了,更多相关android长按圆环动画内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android实现动态圆环的图片头像控件

    先看效果图: 现在大部分的app上难免会使用到圆形头像,所以今天我给大家分享一个单独使用的,并且周围带有圆环动画的花哨圆形头像控件,本控件是在圆形头像控件基础上实现的,只是在其周围再画一些不同大小的圆而已,就可以实现如图的效果. 圆形头像的基本原理是将设置的资源文件转化成Bitmap,然后通过BitmapShader类将Bitmap成为Paint的渲染器,然后在onDraw()中通过canvas.drawCircle(rx,ry,radius,paint);画布上画圆,而这个圆就是形成了圆形头像

  • Android自定义View之酷炫圆环(二)

    先看下最终的效果 静态: 动态: 一.开始实现 新建一个DoughnutProgress继承View public class DoughnutProgress extends View { } 先给出一些常量.变量以及公共方法的代码,方便理解后面的代码 private static final int DEFAULT_MIN_WIDTH = 400; //View默认最小宽度 private static final int RED = 230, GREEN = 85, BLUE = 35;

  • Android开发笔记之:在ImageView上绘制圆环的实现方法

    绘制圆环其实很简单,有大概以下三种思路. 这里先说网上提到的一种方法.思路是先绘制内圆,然后绘制圆环(圆环的宽度就是paint设置的paint.setStrokeWidth的宽度),最后绘制外圆.请看核心源码: 复制代码 代码如下: <SPAN xmlns="http://www.w3.org/1999/xhtml">package yan.guoqi.rectphoto;import android.content.Context;import android.graph

  • Android自定义view绘制圆环占比动画

    一.实现效果图 二.核心代码 1.自定义MyProgressView.java package com.czhappy.effectdemo.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas;

  • Android自定义View之酷炫数字圆环

    先看下最终的效果 一.开始实现 新建一个DoughnutView继承View public class DoughnutView extends View { } 先重写onMeasure方法. /** * 当布局为wrap_content时设置默认长宽 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int hei

  • Android自定义带动画的半圆环型进度效果

    本文实例为大家分享了Android半圆环型进度效果的具体代码,供大家参考,具体内容如下 package com.newair.ondrawtext; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Can

  • Android实现长按圆环动画View效果的思路代码

    一.需求来源 最近想到一个需求,类似悦跑圈或者Keep的结束按钮动画 二.思路代码 该动画按钮的主要作用就是防止用户误操作,具体实现思路如下: 1.监听用户的触摸事件OnTouchListener,在ACTION_DOWN的时候,记录下xy坐标和触摸时间,同时start自定义View动画:在ACTION_MOVE的过程中,判断坐标差值的偏移量是否在一个可接受的范围内,是的话就保留当前动画,不是的话就清除按钮上绘制的path:在ACTION_UP的时候,再次记录下触摸时间,比较两个时间是否达到了长

  • Android实现随意拖动View效果的实例代码

    项目过程中要实现能在页面中随意的拖动,刚开始实现是用悬浮球的形式进行实现,因为之前项目中用过,实现后发现用户每次安装后,都有权限的限制,甚至有些用户关闭悬浮球权限之后,不知道怎么在手机上打开悬浮球的权限,这样的话用户体验很不好,所以自己重新自定义实现在页面中拖动,不需要请求权限. 自定义随意拖动View: package com.dragdemo; import android.annotation.SuppressLint; import android.content.Context; im

  • Android仿IOS上拉下拉弹性效果的实例代码

    用过iphone的朋友相信都体验过页面上拉下拉有一个弹性的效果,使用起来用户体验很好:Android并没有给我们封装这样一个效果,我们来看下在Android里如何实现这个效果.先看效果,感觉有些时候还是蛮实用的. 思路:其实原理很简单,实现一个自定义的Scrollview方法(来自网上大神),然后在布局文件中使用自定义方法Scrollview就可以了. 代码: 自定义View,继承自Scrollview.MyReboundScrollView类 package com.wj.myrebounds

  • Android打开淘宝客户端(手淘)效果及实现代码

    隐式调用的方法就不讲了,如果安装了手淘的SDK或阿里百川之类的东西请参考官方文档,有了文档这些都不是问题. 一.应用内打开 应用内部调用淘宝,当展示"最近运行的应用"时只会显示一个应用,前提是安装了淘宝客户端. 效果图: 首先判断应用是否安装: private boolean isAppInstalled(Context context, String uri) { PackageManager pm = context.getPackageManager(); boolean ins

  • Android TV开发:实现3D仿Gallery效果的实例代码

    本文讲述了Android TV开发:实现3D仿Gallery效果的实例代码.分享给大家供大家参考,具体如下: 1.实现效果: 滚动翻页+ 页面点击+页码指示器+焦点控制 2.实现这个效果之前必须要了解 Android高级图片滚动控件实现3D版图片轮播器这篇文章,我是基于他的代码进行修改的,主要为了移植到电视上做了按键事件和焦点控制. 3.具体代码: public class Image3DSwitchView extends LinearLayout { private int currentP

  • Android RecycleView滑动停止后自动吸附效果的实现代码(滑动定位)

    最近有个需求 要求列表 滑动后第一条 需要和顶部对齐 上网找了找  发现 官方支持 Recycle + LinearSnapHelper 可以实现 但我实际操作加上后 发现会卡顿 滑动卡顿 没有以前那种流畅感了 想了想  算了 懒得看源码  还是自己写一个得了 效果图 : 代码如下 注释很清楚了 package com.example.testapp import androidx.appcompat.app.AppCompatActivity import android.os.Bundle

  • Android仿高德首页三段式滑动效果的示例代码

    目录 高德的效果 实现的效果 自定义View源码 xml布局中的使用 高德首页按钮处理 源码地址 最近发现很多app都使用了三段式滑动,比如说高德的首页和某宝等物流信息都是使用的三段式滑动方式,谷歌其实给了我们很好的2段式滑动,就是BottomSheet,所以这次我也是在这个原理基础上做了一个小小的修改来实现我们今天想要的效果. 高德的效果 实现的效果 我们实现的效果和高德差距不是很大,也很顺滑.具体实现其实就是继承CoordinatorLayout.Behavior 自定义View源码 /**

  • Android的Activity跳转动画各种效果整理

    大家使用Android的原生UI都知道,Android的Activity跳转就是很生硬的切换界面.其实Android的Activity跳转可以设置各种动画.下面给大家看看效果:  实现非常简单,用overridePendingtransition(int inId, int outId)即可实现.inId是下一界面进入效果的xml文件的id,outId是当前界面退出效果的xml文件id. 效果是用xml文件写的,首先要在res文件夹下建立anim文件夹,然后把动画效果xml文件放到里面去. 下面

  • Android实现雷达View效果的示例代码

    样式效果 还是先来看效果: 这是一个仿雷达扫描的效果,是之前在做地图sdk接入时就想实现的效果,但之前由于赶着毕业设计,就没有亲手去实现,不过现在自己撸一个发现还是挺简单的. 这里主要分享一下我的做法. 目录 主体轮廓的实现(雷达的结构) 动画的实现(雷达扫描的效果) 目标点的加入(图片/点) 主体轮廓实现 不难分析得出,这个View主要由外部的一个圆,中间的锚点圆以及扇形旋转区域组成.而且每个部分理应由不同的Paint去绘制,以方便去定制各部分的样式. 外部圆以及锚点圆的绘制较为简单,主要的点

  • 一文搞懂Android RecyclerView点击展开、折叠效果的实现代码

    RecyclerView是什么 RecycleView是Android5.0后谷歌推出的一个用于在有限的窗口中展示大量数据集的控件,位于support-v7包中.它可以实现与ListView和GridView一样的效果,提供了一种插拔式的体验,高度的解耦,异常的灵活,只需设置其提供的不同的LayoutManager,ItemAnimator和ItemDecoration,就能实现不同的效果. RecyclerView的优点 1.支持局部刷新.    2.可以自定义item增删时的动画.    3

随机推荐