自定义View —— 可伸展的CollapsExpendView

自定义可伸缩的ViewGroup

效果图

具体代码及详解:

主要几个注意点

  1. 在OnMeasure中调用measureChild方法,该方法会调用子View的Measure方法,获取MeasuredWidth和MeasureHeight。之后可以根据这些已测量的数值计算父View的高度。
  2. 在构造函数中执行addView操作将预备添加的view添加上去,包括最初未显示的ImageView,当点击右侧按钮时添加背景图片,再次点击设置背景为空,设置后都进行View的requestLayout和invalidate来重绘。

public class CollapsExpendView extends ViewGroup{
	private static String TAG="CollapsExpendView";
    // 图片数组  
    private static final int[] ARR_IMAGES = {   
        R.drawable.sample_0,   
        R.drawable.sample_1,   
        R.drawable.sample_2,   
    };
    private TextView textview[];
    private ImageButton button[];
    private ImageView imageView[];
    private Context context;
    private Boolean ifexpend=false;
    private int linearLayout_height,linearLayout_width;
    private static final String[] names={
    	"狗111111",
    	"狗222222",
    	"狗333333"
    };
    private LinearLayout linearLayout[];
	public CollapsExpendView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		this.context=context;
		addViewFirst();
	}

	public CollapsExpendView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
		this.context=context;
	}

	public CollapsExpendView(Context context) {
		this(context,null);
		this.context=context;
		// TODO Auto-generated constructor stub
	}
	public void addViewFirst(){
		Log.i(TAG,"addViewFirst");
		linearLayout = new LinearLayout[3];
		textview=new TextView[3];
		button= new ImageButton[3];
		imageView=new ImageView[3];
		for(int i=0;i<3;i++){
			linearLayout[i]=new LinearLayout(context);
			imageView[i]=new ImageView(context);
			//设置宽高大小,这个时候只是在构造函数中执行,还没有到View的Measure阶段,调用get方法获取到的高和宽都是0;
			LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
			linearLayout[i].setOrientation(LinearLayout.HORIZONTAL);
			//给横向的LinearLayout添加三个view
			setLinearLayoutView(linearLayout[i],i);
			linearLayout[i].setLayoutParams(params);
			imageView[i].setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
			//整体的viewGroup添加纵向的三个view,分别是一个Layout,一个分割线,一个图片(由于是wrap_Content最开始不显示),一个是分割线
			this.addView(linearLayout[i]);
			this.addView(imageView[i]);
			this.addView(getDividerView());
		}	
	}
	public View getDividerView(){
		ImageView divider=new ImageView(context);
		LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);
		divider.setLayoutParams(params);
		divider.setBackgroundResource(R.drawable.category_list_divider);
		return divider;
	}
	@Override
	protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
		// TODO Auto-generated method stub
		int count = getChildCount();     
		int sumHeight=0;
        //根据每个子View的设定大小,设置每一个子View的位置
        for(int i = 0 ;i < count;i++) {
        	View child= getChildAt(i);
        	child.layout(0, sumHeight,child.getMeasuredWidth(), sumHeight+child.getMeasuredHeight());
        	sumHeight+=child.getMeasuredHeight();
        }
	}
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
	}
/*
 * 父视图可能在它的子视图上调用一次以上的measure(int,int)方法。
 * 例如,父视图可以使用unspecified dimensions来将它的每个子视图都测量一次来算出它们到底需要多大尺寸,
 * 如果所有这些子视图没被限制的尺寸的和太大或太小,那么它会用精确数值再次调用measure()
 * (也就是说,如果子视图不满意它们获得的区域大小,那么父视图将会干涉并设置第二次测量规则)。
 * @see android.view.View#onMeasure(int, int)
 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		//获取父view的最宽大显示限制
		int rw = MeasureSpec.getSize(widthMeasureSpec);
		int rh = MeasureSpec.getSize(heightMeasureSpec);
		Log.i(TAG,"rw: "+rw+"rh: "+rh);
		int count=this.getChildCount();
		int sumHeight=0;//累加高度
		View child=null;
		for (int i = 0; i < count; i++) {
			child = this.getChildAt(i);
			Log.i(TAG,"child:width》》  "+child.getWidth()+"LayoutParams》》 "+child.getLayoutParams().width+"getMeasuredWidth》》 "+child.getMeasuredWidth());
			this.measureChild(child, widthMeasureSpec, heightMeasureSpec); 
			//在第一次测量中,会使用UNSPECIFIED测量子View期望的size,所以在自定义viewgroup中,
			//调用Measurechild之后才会有getMeasureHeight和getMeasureWidth的值
			Log.i(TAG,"child:width》》  "+child.getWidth()+"LayoutParams》》  "+child.getLayoutParams().width+"getMeasuredWidth》》 "+child.getMeasuredWidth());
			sumHeight+=child.getMeasuredHeight();
		}
		setMeasuredDimension(rw, sumHeight);
	}
	public void setLinearLayoutView(LinearLayout layout,int i){
		//设置textView
		textview[i] =new TextView(context);
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,88);
		textview[i].setLayoutParams(params);
		textview[i].setText(names[i]);
		textview[i].setTextSize(32);
		layout.addView(textview[i],params);
		//设置填充Layout,权重是1
		LayoutParams params2= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1);
		layout.addView(new View(context),params2);
		//设置按钮
		button[i]=new ImageButton(context);
		LayoutParams params_button = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
		button[i].setLayoutParams(params_button);
		button[i].setBackgroundResource(R.drawable.btn_alarms_more);	
		button[i].setOnClickListener(getButtonOnclickListener(button[i],i));
		layout.addView(button[i]);	
	}	
	private OnClickListener getButtonOnclickListener(final ImageButton button, final int i) {
		// TODO Auto-generated method stub
		return new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				if(ifexpend==false){//表示是收缩的,点击后需要展开
					button.setBackgroundResource(R.drawable.btn_alarms_up);	
					ifexpend=true;
					imageView[i].setBackgroundResource(ARR_IMAGES[i]);
				}
				else{
					button.setBackgroundResource(R.drawable.btn_alarms_more);	
					ifexpend=false;
					imageView[i].setBackground(null);
				}
				CollapsExpendView.this.requestLayout();
				CollapsExpendView.this.invalidate();
					
			}
		};
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值