码迷,mamicode.com
首页 > 其他好文 > 详细

ViewGroup自定义控件

时间:2015-10-07 13:27:24      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

1. 简单的控件 View

Imageview Button TextView 共同的父类 View;

2. 控件的容器 ViewGroup

一个容器可以存放多个view对象,并且按照定义的规则去排列这些孩子;
RelativeLayout ,LinearLayout 共同的父类是ViewGroup

如下图:
技术分享

自定义控件:
1.onDraw() 重要的方法,用于画自定义控件的效果;
2.一般把画图所需要的工具如都放在onCreate初始化
new Matrix();
new Paint();  

View

View自定义控件下的两个构造方法:
//如果采用的是xml布局资源文件 创建view对象,使用两个参数的构造方法.
setContentView(R.layout.activity_main);
//代码方式new出来view对象,使用的是一个参数的构造方法.
MyView myview = new MyView(this);

ViewGroup

ViewGroup的下的构造方法也与View作用一样;
注意:
在控件显示到界面之前,必须要先去计算孩子的宽高;

上下兼容可以使用ViewPager 导用v4包;
技术分享

ViewGroup重要方法:

OnMeasure() 
都是爹调用孩子,
1.用于测量ViewGroup里面,孩子view的宽度和高度;
2.子类如果需要控制自己大小时复写;
技术分享
注意
1.measure()后才可以getMeasuredWidth()
2.如果OnMeasure没有调用super.onMeasure()就需要调用下面这句话:
   setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);  

// measure(100,200)//父容器调用孩子的
// 参数:widthMeasureSpec,heightMeasureSpec
// 父容器测量孩子时,会给宽高值进来,让孩子自己按照这个宽高布局

// int mode = MeasureSpec.getMode(widthMeasureSpec);//获得模式
// int size = MeasureSpec.getSize(widthMeasureSpec);//获得size

// widthMeasureSpec:组成
// 由 32位的二进制码组成的:0101010110....
// 头两位表示的是模式:
// 1. UNSPECIFIED : 未指定的
// 2. EXACTLY:精确的
// 3.AT_MOST:最大
// 后面的30位表示的是 大小 :010101--->



onLayout()
1.onMeasure方法对控件测量完后调用,用于控制孩子的显示位置;
2. ViewGroup下的onLayout是用于管理它的孩子的,所以ViewGroup会强制子类去复写;而View是没有孩子的,因此复写它也没用(View下的onLayout是空的,不会);

scrollBy()
从当前位置进行移动,每次移动会参照当前坐标而增量;(移动的是手机窗体)
scrollTo()
参照左上角坐标(0,0)进行移动;每次移动都会根据顶点坐标,下次移动还是会根据顶点坐标(0,0)进行移动;(移动的是手机窗体)
注意:左菜单与主页是不会移动的,每次移动的是手机窗体;
技术分享



ViewGroup分析图:
技术分享




实例代码如下:
package com.bobo.viewgroup;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class MyGroupView extends ViewGroup {
    private LinearLayout left;
    private LinearLayout middle;
    private LinearLayout right;
    private int measuredWidth;
    private int measuredHeight;
    /**
     *使用XML配置文件显示界面的时候调用
     */
    public MyGroupView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }
    /**
     *使用代码显示界面的时候调用
     */
    public MyGroupView(Context context) {
        super(context);
        initView(context);
    }
    // 初始化界面
    private void initView(Context context) {
        // 给出孩子的宽高
        left = new LinearLayout(context);
        left.setBackgroundColor(Color.BLUE);
        left.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        middle = new LinearLayout(context);
        middle.setBackgroundColor(Color.RED);
        middle.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        right = new LinearLayout(context);
        right.setBackgroundColor(Color.GREEN);
        right.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        // 添加孩子到ViewGroup
        this.addView(left);
        this.addView(middle);
        this.addView(right);
    }
    // 显示界面之前一定要去测量孩子的宽高
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 测量孩子的宽高
        left.measure(widthMeasureSpec, heightMeasureSpec);
        middle.measure(widthMeasureSpec, heightMeasureSpec);
        right.measure(widthMeasureSpec, heightMeasureSpec);
        // 获取测量后的宽高(注意只有 先measure才可以getMeasuredWidth)
        measuredWidth = left.getMeasuredWidth();
        measuredHeight = left.getMeasuredHeight();
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    // 控制孩子的显示位置
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        left.layout(-measuredWidth, 0, 0, measuredHeight);
        middle.layout(0, 0, measuredWidthmeasuredHeight);
        right.layout(measuredWidth, 0, measuredWidth * 2, measuredHeight);
    }
    int startX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = (int) event.getRawX();
            break;
        case MotionEvent.ACTION_MOVE:
            int newX = (int) event.getRawX();
            int dx = newX - startX;
            // 相对当前位置进行移动
            scrollBy(-dx, 0);
            // 重新获取当前位置
            startX = (int) event.getRawX();
            invalidate();//更新
            break;
        case MotionEvent.ACTION_UP:
            break;
        }
        return true;
    }
}






ViewGroup自定义控件

标签:

原文地址:http://www.cnblogs.com/relice/p/4858560.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!