自定义ViewGroup的一个小例子

自定义ViewGroup的的讲解有很多,没必要再过多的赘述,网上一搜一大把,下面写一个简单的例子,供自己以后复习的时候可以用到。

  • 自定义属性
    在values下面新建一个attrs.xml文件,用来自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CascadeLayout">
        <attr name="horizontal_spacing" format="dimension"/>
        <attr name="veritcal_spacing" format="dimension"/>
    </declare-styleable>
</resources>
  • 新建两个属性的默认的尺寸大小在dimens.xml文件中
 <dimen name="default_horizontal_spacing">15dp</dimen>
 <dimen name="default_vertical_spacing">15dp</dimen>
  • 构建我们的主体类CascadeLayout
package com.gearmotion.app.cascadeviewgroupmotion;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Charles on 2016/3/22.
 */
public class CascadeLayout extends ViewGroup {

   //水平间距
   private int mHorizontalSpacing;
   //垂直间距
   private int mVerticalSpacing;

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

   public CascadeLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
      TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CascadeLayout);
      mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.CascadeLayout_horizontal_spacing,
              this.getResources().getDimensionPixelSize(R.dimen.default_horizontal_spacing));
      mVerticalSpacing = a.getDimensionPixelSize(R.styleable.CascadeLayout_veritcal_spacing, this
              .getResources().getDimensionPixelSize(R.dimen.default_vertical_spacing));
      a.recycle();
   }

   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      final int count = this.getChildCount();
      int width = 0;
      int height = 0;
      for (int i = 0; i < count; i++) {
         View currentView = this.getChildAt(i);
         //对每个子view测量
         measureChild(currentView, widthMeasureSpec, heightMeasureSpec);
         LayoutParams lp = (LayoutParams) currentView.getLayoutParams();
         width = getPaddingLeft() + mHorizontalSpacing * i;
         height = getPaddingTop() + mVerticalSpacing * i;
         //设置每个子view的坐标信息
         lp.x = width;
         lp.y = height;
      }
      width += getChildAt(count - 1).getMeasuredWidth();
      height += getChildAt(count - 1).getMeasuredHeight();
      setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height,
              heightMeasureSpec));
   }

   @Override
   protected void onLayout(boolean changed, int l, int t, int r, int b) {
      final int count = this.getChildCount();
      for (int i = 0; i < count; i++) {
         View view = this.getChildAt(i);
         LayoutParams lp = (LayoutParams) view.getLayoutParams();
         view.layout(lp.x, lp.y, lp.x + view.getMeasuredWidth(), lp.y + view.getMeasuredHeight());
      }
   }

   @Override
   protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
      return p instanceof LayoutParams;
   }

   @Override
   protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
      return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams
              .WRAP_CONTENT);
   }

   @Override
   protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
      return new LayoutParams(p);
   }

   //创建自定义LayoutParams用来记录位置信息
   private static class LayoutParams extends ViewGroup.LayoutParams {
      //用来保存坐标信息
      public int x;
      public int y;

      public LayoutParams(Context c, AttributeSet attrs) {
         super(c, attrs);
      }

      public LayoutParams(ViewGroup.LayoutParams source) {
         super(source);
      }

      public LayoutParams(int width, int height) {
         super(width, height);
      }
   }
}
  • xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<com.gearmotion.app.cascadeviewgroupmotion.CascadeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ns="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ns:horizontal_spacing="20dp"
    ns:veritcal_spacing="20dp"
    tools:context="com.gearmotion.app.cascadeviewgroupmotion.MainActivity">

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#668B8B"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#00FF00"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#FF6A6A"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#9BCD9B"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#000080"/>
</com.gearmotion.app.cascadeviewgroupmotion.CascadeLayout>
  • 最后显示的效果如下:
    这里写图片描述
原文地址:https://www.cnblogs.com/summerpxy/p/13648336.html