ViewGroup自定义控件

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;
    }
 
}
 
 





转载于:https://www.cnblogs.com/relice/p/4858560.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值