自绘控件开发探索2-让view动起来

本文探讨自绘控件的动态更新,通过分析postInvalidate与invalidate方法,揭示界面刷新机制。示例展示了随手指移动的动态效果,支持多种自定义属性,适用于音量、满意度等场景。同时介绍了已有的自定义视图MyStandardView。
摘要由CSDN通过智能技术生成

前面讲到,自绘控件就是一块显示区域而已,绘制完了之后再想更改界面,就必须使用invalidate方法。

postInvalidate方法和invalidate方法都能够使得界面刷新。

1:我们先看一下postInvalidate方法,里面只有一句,调用postInvalidateDelayed方法:

AttachInfo 是个啥呢?a set of information given to a view when it is attached to its parent window,

dispatchInvalidateDelayed会使用view的ViewRootHandler 发送一条信息到消息队列的末端,处理信息时,调用view的invalidate方法。所以,postInvalidate方法最终会调用invalidate方法。

2:invalidate方法,该方法会使得view树重绘。如果你更改了某些属性值,重绘的时候就会直观的看到。所以,让你的view动起来的level1
方案就是改变属性值然后invalidate,每次改变一点点,就能使view缓慢的动起来。
 
 

光说不练家把什,先上效果图:


动态效果就是随着手指的移动,它会跟着你动。支持许多自定义属性,可以满足需要从零到100%选择的所有需求,如音量,满意度等。支持各种自定义

MyStandardView上一个坑里已经介绍过了。

public class MyView_ArcScale extends MyStandardView {

    private int smaller;
    private int finalHeight;
    private int finalWidth;
    private float mScale = 0;//degree

    private int inCricleColor = Color.BLUE;
    private int outArcColor = Color.GREEN;
    private int textColor = Color.BLACK;

    private float outArcWidth = 20;
    private int startDegree = 0;//degree
    private float testSize = 15;
    private Paint mPaint;

    private float halfHeight; //圆心坐标
    private  float halfWidth;//圆心坐标
    public MyView_ArcScale(Context context) {
        this(context, null, 0);
    }

    public MyView_ArcScale(Context context, AttributeSet attrs) {

        this(context, attrs, 0);
    }

    public MyView_ArcScale(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        final TypedArray typedArray = context.obtainStyledAttributes(attrs,
                R.styleable.MyView_ArcScale);
        this.inCricleColor = typedArray.getColor(R.styleable.MyView_ArcScale_inCircleColor, inCricleColor);
        this.outArcColor = typedArray.getColor(R.styleable.MyView_ArcScale_outArcColor, outArcColor);
        this.textColor = typedArray.getColor(R.styleable.MyView_ArcScale_testColor, textColor);
        this.outArcWidth = typedArray.getDimension(R.styleable.MyView_ArcScale_outArcWidth, outArcWidth);
        this.startDegree = typedArray.getInt(R.styleable.MyView_ArcScale_degreeStart, startDegree);
        this.testSize = typedArray.getDimension(R.styleable.MyView_ArcScale_testSize, testSize);
        typedArray.recycle();//回收资源
        mPaint = new Paint();
        this.mScale=startDegree;//初始时默认不画外部弧形。
    }

    @Override
    public int getDefaultHeight() {
        return 200;
    }

    @Override
    public int getDefaultWidth() {
        return 200;
    }


    /**
     *
     * @param mScale >0且<360
     */
    public void setmScale(float mScale) {
        if(mScale<0||mScale>360){
            try {
                throw new Exception("mScale must between 0-360");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
        this.mScale = mScale;
        postInvalidate();

    }

    /**
     *
     * @param startDegree 三点钟方向为0,顺时针为正向
     */
    public void setStartDegree(int startDegree) {
        if(mScale<0||mScale>360){
            try {
                throw new Exception("startDegree must between 0-360");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
        this.startDegree = startDegree;
        postInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        finalHeight = getFinalHeight();
        finalWidth = getFinalWidth();
        smaller = finalHeight > finalWidth ? finalWidth : finalHeight;
        int radiusIn = smaller / 4;
        int radiusOut = smaller / 2;
        halfHeight = finalHeight / 2;
        halfWidth = finalWidth / 2;

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(inCricleColor);

        canvas.drawCircle(halfWidth, halfHeight, radiusIn, mPaint);

        mPaint.setStrokeWidth(this.outArcWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(this.outArcColor);

        float magin = outArcWidth / 2;
        RectF mRectF = new RectF(
                (halfWidth - radiusOut + magin),
                (halfHeight - radiusOut + magin),
                (halfWidth + radiusOut - magin),
                (halfHeight + radiusOut - magin));

        canvas.drawArc(mRectF, this.startDegree, mScale, false, mPaint);
        //消除字体锯齿
        mPaint.setStrokeWidth(2);
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(this.textColor);
        mPaint.setTextSize(this.testSize);


        canvas.drawText(((int)(mScale / 360 * 100) + "") + "%",
                halfWidth - testSize,
                halfHeight - testSize,
                mPaint);

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float xCricle= event.getX()-halfWidth;//相对于圆心的坐标
        float yCricle=halfHeight-event.getY();

// 圆心坐标xr,yr 三点钟方向为0,顺时针为正向
// 当前坐标x,y
        //求当前坐标所代表的度数。

//startdegree
        float tan= Math.abs( yCricle/xCricle);
        float result= (float) Math.toDegrees( Math.atan(tan));
//        L.d("---aaa"+result);
        /**
         * 以三点钟为起始,以顺时针为正向,点击点的度数。
         */
        float fDegree=0;
        if(xCricle==0&&yCricle==0){
            return  true;
        }
        else if(xCricle==0&&yCricle!=0){
            if(yCricle>0)fDegree=270;
            else fDegree=90;
        }
        else if(xCricle!=0&&yCricle==0){
            if(xCricle>0)fDegree=0;
            else fDegree=180;
        }
        else if(xCricle>0&&yCricle<0){
            fDegree=result;
//            L.d("1");
        }
        else if(xCricle<0&&yCricle<0){
           fDegree=180-result;
//            L.d("2");
        }
        else if(xCricle<0&&yCricle>0){
            fDegree=result+180;
//            L.d("3");
        }
        else if(xCricle>0&&yCricle>0){
            fDegree=360-result;
//            L.d("4");
        }
//        L.d(event.getX()+"---is"+halfWidth+"---is"+xCricle+"----is"
//                +event.getY()+"---is"+halfHeight+"---is"+yCricle+"----is"+result);

        float lastmScale=mScale;



        float newmScale=0;
        //改变mscale的值,使得外层弧线参数改变
        if(fDegree<startDegree)newmScale= (float) (360-(startDegree-fDegree));
        else  newmScale= (float) (fDegree-startDegree);


        mScale=newmScale;
        invalidate();
//        L.d(fDegree+"");
        return true;
    }

}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView_ArcScale">
        <attr name="inCircleColor" format="reference" />
        <attr name="outArcColor" format="reference" />
        <attr name="testColor" format="reference" />
        <attr name="outArcWidth" format="dimension" />
        <attr name="testSize" format="dimension" />
        <attr name="degreeStart" format="integer" />

    </declare-styleable>
</resources>

and,布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/aaaaa">
    <com.example.administrator.ysdgo.weidget.MyView_ArcScale
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center_vertical"
        android:padding="10dp"

        app:inCircleColor="@color/colorAccent"
        app:outArcColor="@color/cc_dot_orage"
        app:degreeStart="90"

        android:id="@+id/myview_arcScale"

        />


</LinearLayout>
复杂的地方就在于坐标的转化啦哈哈,然鹅也不是很复杂,就是获得事件发生的点后去计算角度,然后设置角度,然后invalidate方法。

注意:画弧线的起始角度是三点钟方向,正向是顺时针。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值