有动态效果的自定义View

自定义View,通过手势动态变化

实现效果:自定义一个View,通过手势监听事件重绘视图。
1.效果图
点击前:
在这里插入图片描述
点击屏幕前和点击屏幕后,视图的变化。
2.制作过程:
在这里插入图片描述
程序文件。
需要a:属性文件。自定义属性。
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?> b.新建自定义视图View类。并继承手势接口。 public class RoundView extends View implements GestureDetector.OnGestureListener 4个构造函数。 public RoundView(Context context){ this(context,null); }
public RoundView(Context context, AttributeSet attributeSet){
    this(context,attributeSet,0);
}
//如果可以传入NULL值,则标记为@Nullable,如果不可以,则标注为@Nonnull
public RoundView(Context context, @Nullable AttributeSet attributeSet,int defStyleAttr){
    this(context,attributeSet,defStyleAttr,0);
}
public RoundView(Context context, @Nullable AttributeSet attributeSet,int defStyleAttr,int defStyleRes){
    super(context,attributeSet,defStyleAttr,defStyleRes);
    //获取属性值,默认0 ?
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet,R.styleable.RoundView);
    mRingRadius = typedArray.getDimension(R.styleable.RoundView_radius,0);
    mRingWidth = typedArray.getDimension(R.styleable.RoundView_ring_width,0);
    mRingColor = typedArray.getColor(R.styleable.RoundView_ring_color, getResources().getColor(R.color.ring_background));

    mProgressRadius = typedArray.getDimension(R.styleable.RoundView_progress_ring_radius,0);
    mProgressWidth = typedArray.getDimension(R.styleable.RoundView_progress_ring_width,0);
    mProgressRingColor = typedArray.getColor(R.styleable.RoundView_progress_ring_color,getResources().getColor(R.color.colorAccent));
    typedArray.recycle();

    /**
     * 随着Android SDK升级前某些接口能有更好、更安全接口来代替Android开发团队会把过时接口标识成deprecated, 开发文档提示使用新代替接口用GestureDetector构造函数4.1版本已经过时使用推荐:
     mGestureDetector = new GestureDetector(this, this);
     // 注意前this代表Context,this代表OnGestureListener
     // Activity继承自Context, 而activity应该实现了(implements)OnGestureListener接口
     */
    mGestureDetector = new GestureDetector(context,this);
    init();
}

最后一个构造函数中有怎么使用自定义属性的方法。
C:重写Ondraw()函数。
@Override
public void onDraw(Canvas canvas){
x0 = getWidth()/2;
y0 = getHeight()/2;

    mRingRadius = mRingRadius == 0 ? Math.min(getHeight()/2, getWidth()/2):mRingRadius;//没有给出属性值时,设置一个值
    mRingWidth = mRingWidth == 0 ? mRingRadius/5 : mRingWidth;
    //mRingRadius = mRingRadius - mRingWidth/2;//圆环真正的半径
    mRingPaint.setStrokeWidth(mRingWidth);
    canvas.drawCircle(x0,y0,mRingRadius,mRingPaint);

    mProgressWidth = mProgressWidth == 0 ? mRingWidth/2 : mProgressWidth;
    mProgressRingPaint.setStrokeWidth(mProgressWidth);
    canvas.drawArc(new RectF(x0 - mRingRadius,y0 - mRingRadius,x0 + mRingRadius,y0 + mRingRadius),
            startAngle,sweepAngle,false,mProgressRingPaint);
}

设置属性的值,画两个圆圈。
效果如图1所示。
d.重写手势监听接口的7个函数。
在这些函数中重写设置属性值,然后重新绘图即可。

@Override
public boolean onTouchEvent(MotionEvent e){
//把onTouchEvent托管给GestureDetector
return mGestureDetector.onTouchEvent(e);
}

@Override
public boolean onDown(MotionEvent e) {
    //单击事件
    sweepAngle = sweepAngle + 2;//每次单击增加5度
    if(sweepAngle >= 360){
        sweepAngle = 0;
    }
    invalidate();
    return false;
}
@Override
public void onShowPress(MotionEvent e) {// 在Touch down之后一定时间(115ms)触发
}
@Override
public boolean onSingleTapUp(MotionEvent e) {// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
    return false;
}
@Override
public void onLongPress(MotionEvent e) {
    //sweepAngle = sweepAngle + 20;//每次单击增加18度
    //invalidate();
    // 长按后触发(Touch down之后一定时间(500ms))
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float x1, float x2){
    //没有效果
    double st1 = Math.atan((e1.getY() - y0)/(e1.getX() - x0));
    double st2 = Math.atan((e2.getY() - y0)/(e2.getX() - x0));
    sweepAngle = sweepAngle + (float)st2 - (float)st1;
    invalidate();
    return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    return false;
}
 invalidate():在主线程中重新调用onDraw()函数。
 e:activity使用。
 <!--设置自定义属性值APP:-->
<com.example.chengwenbo.mycustomview.RoundView
    android:id="@+id/my_roundview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:radius="120dp"
    app:ring_width="20dp"
    app:progress_ring_width="10dp"/>
    在布局文件可以设置属性值,也可以在代码中设置。
  
 3.总结。
 View子类中重新绘图,用invalidate()。
 实现动态View的方法有很多种,这种是通过user的手势设置数据,重新绘制。还可以通过动画效果等实现。
 完整的自定义view源代码。
 package com.example.chengwenbo.mycustomview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RoundView extends View implements GestureDetector.OnGestureListener{

private GestureDetector mGestureDetector;

private float mRingRadius = 0;
private float mRingWidth = 0;
private int mRingColor = 0;

private float mProgressRadius = 0;
private float mProgressWidth = 0;
private int mProgressRingColor = 0;

private Paint mRingPaint;
private Paint mProgressRingPaint;

float x0 = 0;//圆圆心
float y0 = 0;
float startAngle = -90;//圆环开始角度
float sweepAngle = 90;

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

public RoundView(Context context, AttributeSet attributeSet){
    this(context,attributeSet,0);
}
//如果可以传入NULL值,则标记为@Nullable,如果不可以,则标注为@Nonnull
public RoundView(Context context, @Nullable AttributeSet attributeSet,int defStyleAttr){
    this(context,attributeSet,defStyleAttr,0);
}
public RoundView(Context context, @Nullable AttributeSet attributeSet,int defStyleAttr,int defStyleRes){
    super(context,attributeSet,defStyleAttr,defStyleRes);
    //获取属性值,默认0 ?
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet,R.styleable.RoundView);
    mRingRadius = typedArray.getDimension(R.styleable.RoundView_radius,0);
    mRingWidth = typedArray.getDimension(R.styleable.RoundView_ring_width,0);
    mRingColor = typedArray.getColor(R.styleable.RoundView_ring_color, getResources().getColor(R.color.ring_background));

    mProgressRadius = typedArray.getDimension(R.styleable.RoundView_progress_ring_radius,0);
    mProgressWidth = typedArray.getDimension(R.styleable.RoundView_progress_ring_width,0);
    mProgressRingColor = typedArray.getColor(R.styleable.RoundView_progress_ring_color,getResources().getColor(R.color.colorAccent));
    typedArray.recycle();

    /**
     * 随着Android SDK升级前某些接口能有更好、更安全接口来代替Android开发团队会把过时接口标识成deprecated, 开发文档提示使用新代替接口用GestureDetector构造函数4.1版本已经过时使用推荐:
     mGestureDetector = new GestureDetector(this, this);
     // 注意前this代表Context,this代表OnGestureListener
     // Activity继承自Context, 而activity应该实现了(implements)OnGestureListener接口
     */
    mGestureDetector = new GestureDetector(context,this);
    init();
}

@Override
public boolean onTouchEvent(MotionEvent e){
    //把onTouchEvent托管给GestureDetector
    return mGestureDetector.onTouchEvent(e);
}

@Override
public boolean onDown(MotionEvent e) {
    //单击事件
    sweepAngle = sweepAngle + 2;//每次单击增加5度
    if(sweepAngle >= 360){
        sweepAngle = 0;
    }
    invalidate();
    return false;
}
@Override
public void onShowPress(MotionEvent e) {// 在Touch down之后一定时间(115ms)触发
}
@Override
public boolean onSingleTapUp(MotionEvent e) {// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
    return false;
}
@Override
public void onLongPress(MotionEvent e) {
    //sweepAngle = sweepAngle + 20;//每次单击增加18度
    //invalidate();
    // 长按后触发(Touch down之后一定时间(500ms))
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float x1, float x2){
    //没有效果
    double st1 = Math.atan((e1.getY() - y0)/(e1.getX() - x0));
    double st2 = Math.atan((e2.getY() - y0)/(e2.getX() - x0));
    sweepAngle = sweepAngle + (float)st2 - (float)st1;
    invalidate();
    return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    return false;
}

public void init(){
    mRingPaint = new Paint();
    mRingPaint.setAntiAlias(true);
    mRingPaint.setStyle(Paint.Style.STROKE);
    mRingPaint.setColor(mRingColor);

    mProgressRingPaint = new Paint();
    mProgressRingPaint.setAntiAlias(true);
    mProgressRingPaint.setStyle(Paint.Style.STROKE);
    mProgressRingPaint.setColor(mProgressRingColor);
    mProgressRingPaint.setStrokeCap(Paint.Cap.ROUND);
}

@Override
public void onDraw(Canvas canvas){
    x0 = getWidth()/2;
    y0 = getHeight()/2;

    mRingRadius = mRingRadius == 0 ? Math.min(getHeight()/2, getWidth()/2):mRingRadius;//没有给出属性值时,设置一个值
    mRingWidth = mRingWidth == 0 ? mRingRadius/5 : mRingWidth;
    //mRingRadius = mRingRadius - mRingWidth/2;//圆环真正的半径
    mRingPaint.setStrokeWidth(mRingWidth);
    canvas.drawCircle(x0,y0,mRingRadius,mRingPaint);

    mProgressWidth = mProgressWidth == 0 ? mRingWidth/2 : mProgressWidth;
    mProgressRingPaint.setStrokeWidth(mProgressWidth);
    canvas.drawArc(new RectF(x0 - mRingRadius,y0 - mRingRadius,x0 + mRingRadius,y0 + mRingRadius),
            startAngle,sweepAngle,false,mProgressRingPaint);
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值