自定义View

 基于Android UI组件的实现原理,开发者完全可以开发出项目定制的组件,即当Android系统提供的UI组件不足以满足项目需要时,开发者可以通过继承View来派生自定义组件。

 当开发者打算派生自己的UI组件时,首先定义一个继承View基类的子类,然后重写View类的一个或多个方法。通常可以被用户重写的方法下:
  1. View的方法

    当需要自定义开发View时,不需要重写下面的所有方法,可以根据业务的需求重写下面的方法
    构造器:重写构造器是定制View的最基本的方式,当Java代码创建一个View实例,或根据XML布局文件加载并构建界面是将需要调用该构造器
    onFinishInflate():这是一个回调方法,当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法将会被回调。
    onLayout(boolean,int,int,int,int):当该组件需要分配其子组件位置的、大小时,该方法就会被回调。
    onSizeChanged(int,int,int,int): 当该组件的大小发生改变时回调该方法。
    onDraw(Canvas):当该组件将要回执它的内容时回调该方法进行绘制。
    onKeyDown(int,KeyEvent):当某个键被按下时出发该方法。
    onKeyUp(int,KeyEvent):当松开摸个键时触发该方法。
    onTrackballEvent(MotionEvent):放发生轨迹球时间时触发该方法
    onTouchEvent(MotionEvent):当发生触摸屏事件时触发该方法。
    onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect):当该组件焦点发生改变时触发该方法。
    onWindowFocusChanged(boolean):当包含该组件的窗口失去或得到焦点时触发该方法。
    onAttachedToWindow():当把该组件放入某个窗口时触发该方法。
    onDetachedFromWindow():当把该组件从某个窗口上分离时触发该方法。
    onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发该方法。

  2. 举例
    自定义一个子类继承自View

public class CustomView extends View{}

在布局界面定义该控件 为该类的 包名.类名

<包名.CustomView  
     android:id="@+id/***"
     android:layout_width="match_parent"
     android:layout_height="match_parent" 
     />

画图

@Override
        protected void onDraw(Canvas canvas) {
            try {
                Paint paint=new Paint();
                paint.setColor(Color.RED);
                //用矩形画背景
                Rect rect=new Rect
                        (0, 0, viewWidth, viewHeight);
                canvas.drawRect(rect, paint);
                //在布局文件中单位可以是dp,sp,px
                //在代码的单位是px
                paint.setTextSize(30);
                //得文字宽度
                Rect stringSizeRect=new Rect();
                String lastTime=list.get(list.size()-1)
                        .get("time");
                paint.getTextBounds
                (lastTime, 0, lastTime.length(),
                        stringSizeRect);                
                int lastTimeWidth=stringSizeRect.width();

                gap=(viewWidth-lastTimeWidth*2)/(list.size()-1);
                paint.setColor(Color.WHITE);

                int priceHeight=viewHeight-
                        stringSizeRect.height();
                //画时间
                for(int i=0;i<list.size();i++)
                {
                    HashMap<String, String> map=
                            list.get(i);
                    String time=map.get("time");
                    canvas.drawText
                    (time, i*gap, viewHeight, paint);
                    //画价格
                    String strCurrentPrice=map.get("price");
                    int intCurrentPrice=Integer.parseInt
                            (strCurrentPrice);
                    int priceY=intCurrentPrice*priceHeight
                            /maxPrice;
                    priceY=priceHeight-priceY;
                    //最大的价格画到控件外面,要向下移
                    priceY=priceY+stringSizeRect.height();

                    canvas.drawText(strCurrentPrice,
                            i*gap, priceY, paint);

                    //画线
                    if (i<list.size()-1)
                    {
                    int startX=i*gap;
                    int startY=priceY;
                    int stopX=(i+1)*gap;
                    int stopY=0;
                    int nextPrice=Integer.parseInt
                            (list.get(i+1).get("price"));
                    stopY=nextPrice*priceHeight/maxPrice;
                    stopY=priceHeight-stopY;
                    stopY=stopY+stringSizeRect.height();
                    canvas.drawLine
                    (startX, startY, stopX, stopY, paint);
                    }
                }

            //从左到右画线
                if (lineY>0)
                {
                    canvas.drawLine
                    (0, lineY, viewWidth, lineY, paint);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

在MainActivity 中

    Handler handler = new Handler();
    boolean isRunning = true;
    boolean isExit=false;
    @Override
    protected void onDestroy() {
isExit=true;
        super.onDestroy();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        Log.i("onTouchEvent", "" + action);
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            isRunning = !isRunning;
        }
        Log.i("onTouchEvent", "isRunning=" + isRunning);
        return super.onTouchEvent(event);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ArrayList<HashMap<String, String>> list = getData();
        Log.i("", "" + list.size());
        final CustomView customView = (CustomView) findViewById(R.id.customView);
        customView.setData(list);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isRunning) {
                    customView.setData(getData());
                    // 调用onDraw()
                    // 直接调不行
                    // customView.onDraw(canvas);
                    // 间接调onDraw()
                    // invalidate 无效--》屏幕无效--》重新绘制
                    // handler.sendMessage 间接调用handleMessage
                    // sendBroadcast间接调用onReceiver
                    // 更新view 1,invalidate 2,notifyDataSetchanged
                    customView.invalidate();
                }
//用到线程,必须保存线程能结束。
                if (isExit==false)
                {
                handler.postDelayed(this, 1000);
                }

                Log.i("handler.postDelayed", "run" + System.currentTimeMillis());
            }
        }, 1000);
    }

    Random random = new Random();

    public ArrayList<HashMap<String, String>> getData() {
        // 9 3200
        // 10 5000
        // 数据类型表示
        ArrayList<HashMap<String, String>> list = new ArrayList();

        HashMap<String, String> map = new HashMap();
        map.put("time", "9");
        map.put("price", String.valueOf(random.nextInt(8000)));
        list.add(map);

        map = new HashMap();
        map.put("time", "10");
        map.put("price", String.valueOf(random.nextInt(8000)));
        list.add(map);

        map = new HashMap();
        map.put("time", "11");
        map.put("price", String.valueOf(random.nextInt(8000)));
        list.add(map);

        map = new HashMap();
        map.put("time", "13");
        map.put("price", String.valueOf(random.nextInt(8000)));
        list.add(map);
        return list;

    }

这是一个图表的项目,希望对大家能有帮助

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值