Android中自定义View实现圆环等待及相关的音量调节效果_Android

圆环交替、等待效果

效果就这样,分析了一下,大概有这几个属性,两个颜色,一个速度,一个圆环的宽度。
自定View的几个步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure 
4、重写onDraw

1、自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources> 

  <attr name="firstColor" format="color" />
  <attr name="secondColor" format="color" />
  <attr name="circleWidth" format="dimension" />
  <attr name="speed" format="integer" /> 

  <declare-styleable name="CustomProgressBar">
    <attr name="firstColor" />
    <attr name="secondColor" />
    <attr name="circleWidth" />
    <attr name="speed" />
  </declare-styleable> 

</resources> 

2、在View的构造方法中获得我们自定义的属性

/**
   * 第一圈的颜色
   */
  private int mFirstColor;
  /**
   * 第二圈的颜色
   */
  private int mSecondColor;
  /**
   * 圈的宽度
   */
  private int mCircleWidth;
  /**
   * 画笔
   */
  private Paint mPaint;
  /**
   * 当前进度
   */
  private int mProgress; 

  /**
   * 速度
   */
  private int mSpeed; 

  /**
   * 是否应该开始下一个
   */
  private boolean isNext = false; 

  public CustomProgressBar(Context context, AttributeSet attrs)
  {
    this(context, attrs, 0);
  } 

  public CustomProgressBar(Context context)
  {
    this(context, null);
  } 

  /**
   * 必要的初始化,获得一些自定义的值
   *
   * @param context
   * @param attrs
   * @param defStyle
   */
  public CustomProgressBar(Context context, AttributeSet attrs, int defStyle)
  {
    super(context, attrs, defStyle);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomProgressBar, defStyle, 0);
    int n = a.getIndexCount(); 

    for (int i = 0; i < n; i++)
    {
      int attr = a.getIndex(i);
      switch (attr)
      {
      case R.styleable.CustomProgressBar_firstColor:
        mFirstColor = a.getColor(attr, Color.GREEN);
        break;
      case R.styleable.CustomProgressBar_secondColor:
        mSecondColor = a.getColor(attr, Color.RED);
        break;
      case R.styleable.CustomProgressBar_circleWidth:
        mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
        break;
      case R.styleable.CustomProgressBar_speed:
        mSpeed = a.getInt(attr, 20);// 默认20
        break;
      }
    }
    a.recycle();
    mPaint = new Paint();
    // 绘图线程
    new Thread()
    {
      public void run()
      {
        while (true)
        {
          mProgress++;
          if (mProgress == 360)
          {
            mProgress = 0;
            if (!isNext)
              isNext = true;
            else
              isNext = false;
          }
          postInvalidate();
          try
          {
            Thread.sleep(mSpeed);
          } catch (InterruptedException e)
          {
            e.printStackTrace();
          }
        }
      };
    }.start(); 

  } 

3、直接重写onDraw,这不需要重写onMeasure

@Override
  protected void onDraw(Canvas canvas)
  { 

    int centre = getWidth() / 2; // 获取圆心的x坐标
    int radius = centre - mCircleWidth / 2;// 半径
    mPaint.setStrokeWidth(mCircleWidth); // 设置圆环的宽度
    mPaint.setAntiAlias(true); // 消除锯齿
    mPaint.setStyle(Paint.Style.STROKE); // 设置空心
    RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
    if (!isNext)
    {// 第一颜色的圈完整,第二颜色跑
      mPaint.setColor(mFirstColor); // 设置圆环的颜色
      canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环
      mPaint.setColor(mSecondColor); // 设置圆环的颜色
      canvas.drawArc(oval, -90, mProgress, false, mPaint); // 根据进度画圆弧
    } else
    {
      mPaint.setColor(mSecondColor); // 设置圆环的颜色
      canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环
      mPaint.setColor(mFirstColor); // 设置圆环的颜色
      canvas.drawArc(oval, -90, mProgress, false, mPaint); // 根据进度画圆弧
    } 

  } 

大功完成了,当然了,唯一比较纠结的地方就是两个颜色何时切换,如何切换,我采用上面的办法,你也可以自己想想怎么实现。

视频音量调控

这样一个效果使用自定义View来实现的话和圆环的思路差不多,所以我们一起来看:
1、先分许需要的属性,两个小块的颜色、一张中间的图片、间隙大小、一个多少个块块。分析完毕,开始写attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources> 

  <attr name="firstColor" format="color" />
  <attr name="secondColor" format="color" />
  <attr name="circleWidth" format="dimension" />
  <attr name="dotCount" format="integer" />
  <attr name="splitSize" format="integer" />
  <attr name="bg" format="reference"></attr> 

  <declare-styleable name="CustomVolumControlBar">
    <attr name="firstColor" />
    <attr name="secondColor" />
    <attr name="circleWidth" />
    <attr name="dotCount" />
    <attr name="splitSize" />
    <attr name="bg" />
  </declare-styleable> 

</resources> 

2、在构造中获取这些属性:

/**
   * 第一圈的颜色
   */
  private int mFirstColor; 

  /**
   * 第二圈的颜色
   */
  private int mSecondColor;
  /**
   * 圈的宽度
   */
  private int mCircleWidth;
  /**
   * 画笔
   */
  private Paint mPaint;
  /**
   * 当前进度
   */
  private int mCurrentCount = 3; 

  /**
   * 中间的图片
   */
  private Bitmap mImage;
  /**
   * 每个块块间的间隙
   */
  private int mSplitSize;
  /**
   * 个数
   */
  private int mCount; 

  private Rect mRect; 

  public CustomVolumControlBar(Context context, AttributeSet attrs)
  {
    this(context, attrs, 0);
  } 

  public CustomVolumControlBar(Context context)
  {
    this(context, null);
  } 

  /**
   * 必要的初始化,获得一些自定义的值
   *
   * @param context
   * @param attrs
   * @param defStyle
   */
  public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyle)
  {
    super(context, attrs, defStyle);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomVolumControlBar, defStyle, 0);
    int n = a.getIndexCount(); 

    for (int i = 0; i < n; i++)
    {
      int attr = a.getIndex(i);
      switch (attr)
      {
      case R.styleable.CustomVolumControlBar_firstColor:
        mFirstColor = a.getColor(attr, Color.GREEN);
        break;
      case R.styleable.CustomVolumControlBar_secondColor:
        mSecondColor = a.getColor(attr, Color.CYAN);
        break;
      case R.styleable.CustomVolumControlBar_bg:
        mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
        break;
      case R.styleable.CustomVolumControlBar_circleWidth:
        mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
        break;
      case R.styleable.CustomVolumControlBar_dotCount:
        mCount = a.getInt(attr, 20);// 默认20
        break;
      case R.styleable.CustomVolumControlBar_splitSize:
        mSplitSize = a.getInt(attr, 20);
        break;
      }
    }
    a.recycle();
    mPaint = new Paint();
    mRect = new Rect();
  } 

3、重写onDraw

@Override
  protected void onDraw(Canvas canvas)
  {
    mPaint.setAntiAlias(true); // 消除锯齿
    mPaint.setStrokeWidth(mCircleWidth); // 设置圆环的宽度
    mPaint.setStrokeCap(Paint.Cap.ROUND); // 定义线段断电形状为圆头
    mPaint.setAntiAlias(true); // 消除锯齿
    mPaint.setStyle(Paint.Style.STROKE); // 设置空心
    int centre = getWidth() / 2; // 获取圆心的x坐标
    int radius = centre - mCircleWidth / 2;// 半径
    /**
     * 画块块去
     */
    drawOval(canvas, centre, radius); 

    /**
     * 计算内切正方形的位置
     */
    int relRadius = radius - mCircleWidth / 2;// 获得内圆的半径
    /**
     * 内切正方形的距离顶部 = mCircleWidth + relRadius - √2 / 2
     */
    mRect.left = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;
    /**
     * 内切正方形的距离左边 = mCircleWidth + relRadius - √2 / 2
     */
    mRect.top = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth;
    mRect.bottom = (int) (mRect.left + Math.sqrt(2) * relRadius);
    mRect.right = (int) (mRect.left + Math.sqrt(2) * relRadius); 

    /**
     * 如果图片比较小,那么根据图片的尺寸放置到正中心
     */
    if (mImage.getWidth() < Math.sqrt(2) * relRadius)
    {
      mRect.left = (int) (mRect.left + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getWidth() * 1.0f / 2);
      mRect.top = (int) (mRect.top + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getHeight() * 1.0f / 2);
      mRect.right = (int) (mRect.left + mImage.getWidth());
      mRect.bottom = (int) (mRect.top + mImage.getHeight()); 

    }
    // 绘图
    canvas.drawBitmap(mImage, null, mRect, mPaint);
  } 

  /**
   * 根据参数画出每个小块
   *
   * @param canvas
   * @param centre
   * @param radius
   */
  private void drawOval(Canvas canvas, int centre, int radius)
  {
    /**
     * 根据需要画的个数以及间隙计算每个块块所占的比例*360
     */
    float itemSize = (360 * 1.0f - mCount * mSplitSize) / mCount; 

    RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限 

    mPaint.setColor(mFirstColor); // 设置圆环的颜色
    for (int i = 0; i < mCount; i++)
    {
      canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧
    } 

    mPaint.setColor(mSecondColor); // 设置圆环的颜色
    for (int i = 0; i < mCurrentCount; i++)
    {
      canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧
    }
  } 

这里需要注意下:
画块:首先根据块数量和间隙计算,每个块所占的比例。
画图:当图比较大时,直接使用该环内切正方形大小进行约束,当图片比较小时,在正中心的位置绘制。有些数学运算过程,楼主在草稿上画了一会,不复杂,大家自己画画,我就不贴草稿了。

4、添加触摸监听:

/**
   * 当前数量+1
   */
  public void up()
  {
    mCurrentCount++;
    postInvalidate();
  } 

  /**
   * 当前数量-1
   */
  public void down()
  {
    mCurrentCount--;
    postInvalidate();
  } 

  private int xDown, xUp; 

  @Override
  public boolean onTouchEvent(MotionEvent event)
  { 

    switch (event.getAction())
    {
    case MotionEvent.ACTION_DOWN:
      xDown = (int) event.getY();
      break; 

    case MotionEvent.ACTION_UP:
      xUp = (int) event.getY();
      if (xUp > xDown)// 下滑
      {
        down();
      } else
      {
        up();
      }
      break;
    } 

    return true;
  }

触摸监听也得很简单哈,基本能实现,大家也可以加个最小距离加速度什么的,都行。

最后,效果图:

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, view
, 音量
, 自定义view
圆环
android 自定义圆环、安卓自定义圆环、安卓自定义3层圆环、自定义 圆环外 带标注、自定义view画圆环,以便于您获取更多的相关知识。

时间: 2025-01-31 09:57:23

Android中自定义View实现圆环等待及相关的音量调节效果_Android的相关文章

Android中自定义View实现圆环等待及相关的音量调节效果

圆环交替.等待效果 效果就这样,分析了一下,大概有这几个属性,两个颜色,一个速度,一个圆环的宽度. 自定View的几个步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 3.重写onMesure  4.重写onDraw 1.自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="firstColor" f

Android中自定义view实现侧滑效果_Android

效果图: 看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来.但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的. 知识点: 1.ViewDragHelper 的用法: 2.滑动冲突的解决: 3.自定义viewgroup. ViewDragHelper 出来已经比较久了 相信大家都比较熟悉,不熟悉的话google一大把这里主要简单用一下它的几个方法 1.tryCaptureView(View child, int pointerI

Android中自定义view实现侧滑效果

效果图: 看网上的都是两个view拼接,默认右侧的不显示,水平移动的时候把右侧的view显示出来.但是看最新版QQ上的效果不是这样的,但给人的感觉却很好,所以献丑来一发比较高仿的. 知识点: 1.ViewDragHelper 的用法: 2.滑动冲突的解决: 3.自定义viewgroup. ViewDragHelper 出来已经比较久了 相信大家都比较熟悉,不熟悉的话google一大把这里主要简单用一下它的几个方法 1.tryCaptureView(View child, int pointerI

Android中使用TextView实现高仿京东淘宝各种倒计时效果_Android

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

Android 中使用 ViewPager实现屏幕页面切换和页面轮播效果_Android

之前关于如何实现屏幕页面切换,写过一篇博文<Android中使用ViewFlipper实现屏幕切换>,相比ViewFlipper,ViewPager更适用复杂的视图切换,而且Viewpager有自己的adapter,这也让其适应复杂对象,实现数据的动态加载. ViewPager是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一,利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等. 下面我们就展示下Vie

Android 自定View实现仿QQ运动步数圆弧及动画效果_Android

在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个View是如何绘制的. 1.先看效果图 2.效果图分析 功能说明:黄色的代表用户设置的总计划锻炼步数,红色的代表用户当前所走的步数. 初步分析:完全自定义View重写onDraw()方法,画圆弧. 3.画一个圆弧必备知识 在Canvas中有一个画圆弧的方法 drawArc(RectF oval, float startAngle, float sweepA

Android中自定义一个View的方法详解_Android

本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到一些坑,我把自己遇到的一些问题和解决方法总结一下,希望对广大码友们有所帮助. 注意点① 用xml定义Layout时,Root element 最好使用merge 当我们需要继承一个布局比较复杂的ViewGroup(比较多的是LinearLayout.RelativeLayout)时,通常会用xml来

Android中自定义一个View的方法详解

本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到一些坑,我把自己遇到的一些问题和解决方法总结一下,希望对广大码友们有所帮助. 注意点① 用xml定义Layout时,Root element 最好使用merge 当我们需要继承一个布局比较复杂的ViewGroup(比较多的是LinearLayout.RelativeLayout)时,通常会用xml来

Android通过自定义View实现随机验证码_Android

很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章. 一.问题描述 熟悉web开发中童鞋们都知道为了防止恶意破解.恶意提交.刷票等我们在提交表单数据时,都会使用随机验证码功能.在Android应用中我们同样需要这一功能,该如何实现呢,下面我们就自定义一个随机验证码View控件实现这一需求,并且具备通用性,需要的时候在界面中直接加入这个View组件即可. 二.案例介绍 案例运行效