重写Android ----View与ViewGroup

             重写View与ViewGroup

相关资料:

       http://www.gcssloop.com/customview/CustomViewIndex/

https://www.cnblogs.com/Jaylong/p/viewgroup.html

https://www.jianshu.com/p/138b98095778

https://github.com/GcsSloop/AndroidNote/issues/7

(Android 2D操作是要关闭其硬件加速)

                   

1.先说下View与ViewGroup的认识:

   View:我们可以看做一个个展示界面的对象。而ViewGroup就是装View的容器。

所以我们在重写View与ViewGroup的侧重点会有不同。

 View侧重于onDraw(),对自己的长宽测量与设置onMeasure(),绘制。

而ViewGroup侧重于对自己长宽设置,在onMeasure()中setMeasureDimension(w,h),与它们的排放位子onLayout()。

 

2.一步步的实践。

                                上部

 

  重写View的结果图:

     

  准备:

      a.为实验提供数据的,第一个name为numbers的为扇形提供百分比的。第二个是每个扇形的名字。

      

      b.R.id.review

      

 

    c.扇形对象类sector                                                                                                

 

d.MainActivity

 

 

e.重写View的类review

package com.example.reView;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.example.hi.study.R;

import java.util.Arrays;
import java.util.List;

/**
 * Created by hi on 1/15/2018.
 */
public class reView extends View {
    String mtitle;
    int number;
    Paint mPaint;
    int mWidth;
    int mHeiht;
    List<sector> sectors;
    List<Integer> COL= Arrays.asList(Color.BLUE,Color.YELLOW,Color.GREEN,Color.GRAY,Color.DKGRAY);
    float StartAngle=0;
    float currentAngle=0;
    OnClickListener mListener;

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

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

    public reView(final Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.reView);
        mtitle=ta.getString(R.styleable.reView_titles);
        number=ta.getInteger(R.styleable.reView_numbers,0);
        ta.recycle();
//        this.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                Toast.makeText(context,"内部监听事件被点击",Toast.LENGTH_LONG).show();
//            }
//        });
    }

    private void init() {
        mPaint=new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);
    }

    public void setSector(List<sector> list){
        sectors=list;
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mHeiht=h;
        mWidth=w;
        init();
    }
//    @Override
//    public boolean onTouchEvent(MotionEvent event) {
//        mListener.onClick(this);
//        return true;
//    }
//        @Override
//    public void setOnClickListener(OnClickListener l) {
//        mListener=l;
//    }
    @Override
    protected void onDraw(Canvas canvas) {
        if (sectors==null){
            Log.i("sec","sectors  is null");
            return;
        }
        Log.i("info--sectors.size",""+sectors.size());
        canvas.translate(mWidth/2,mHeiht/3);
        int len=mHeiht>mWidth?mWidth:mHeiht;
        int r= (int) ((len/2)*0.8);
        RectF rect=new RectF(-r,-r,r,r);
        for (int i=0;i<sectors.size();i++){
            currentAngle=((float) sectors.get(i).getTime()/1000)*360;
            mPaint.setColor(COL.get(i));
            canvas.drawArc(rect,StartAngle, currentAngle, true, mPaint);
            canvas.save();
            canvas.rotate(StartAngle+currentAngle/2);
            mPaint.setColor(Color.BLACK);
            mPaint.setStrokeWidth(2);
            canvas.drawLine(r,0,r+50,0,mPaint);
            mPaint.setTextSize(25);
            canvas.drawText(sectors.get(i).getWeight()+"%",r/2,0,mPaint);
            canvas.drawText(sectors.get(i).getTitle(),r+80,0,mPaint);
            canvas.restore();
            StartAngle=StartAngle+currentAngle;
        }
        canvas.translate(0,r+200);
        mPaint.setTextSize(50);
        LinearGradient ml=new LinearGradient(0-mPaint.measureText(mtitle)/2,0,0+mPaint.measureText(mtitle)/2,0,Color.YELLOW,Color.BLUE, Shader.TileMode.CLAMP);
        mPaint.setShader(ml);
        canvas.drawText(mtitle,0-mPaint.measureText(mtitle)/2,0,mPaint);
    }




}

 

                               下部

 

从重写ViewGroup

       链接:  http://blog.csdn.net/silently_frog/article/details/79107827

 

 

这里要提下上面用到的关于自定义View与ViewGroup监听事件,自己去百度。这关于事务的分发机制。是Android的一个重点,肯定我要再下一页。

 

 

最后习惯性的提几个知识,便于自己知识的系统性:

ViewManager-----是一个接口类,功能为增加,删除,更新View.

ViewParent------也是一个接口类,功能自己去看源码,现在的我不怎么看的懂。需要说一下,它的实现类ViewGroup这个容器类,所以我猜测其里面应该定义的是ViewGroup容器操作子View特有的方法。

requestLayout()-----这个方法为请求重新布局。它调用自己父容器的requestLayout,其父容器又会调用它的父容器的requestLayout方法,即requestLayout事件层层向上传递,直到DecorView,即根View,而根View又会传递给ViewRootImpl,也即是说子View的requestLayout事件,最终会被ViewRootImpl接收并得到处理。纵观这个向上传递的流程,其实是采用了责任链模式,即不断向上传递该事件,直到找到能处理该事件的上级,在这里,只有ViewRootImpl能够处理requestLayout事件。从measure开始,对于每一个含有标记位的view及其子View都会进行测量、布局、绘制。

invalidate()------ 该方法的调用会引起View树的重绘,常用于内部调用(比如 setVisiblity())或者需要刷新界面的时候,需要在主线程(即UI线程)中调用该方法。

 

requestLayout()是测量、布局、绘制View的,而invalidate()是通知UI更新的。。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值