android根据子view里面的数量自动排版的一个ViewGroup

很多时候 android系统给我们的控件不能满足我们的需求,要使界面做的好,所以大部分都是自己写的控件 。

 

在我做一个 短信群发界面时,需要 这个 自适应子view数量 改变自身高度的 view 所以就自写了一个 这样的控件  

 

现 分享出来 和大家一起共享。  当然  如果朋友 下载了  添加了一些新功能  也请 帮忙 分享 出来 谢谢。

 

大家一起成长。

 

废话少说 上代码:

 

MainActivity

public class MainActivity extends ActionBarActivity implements OnClickListener{

	private Button button;
	private EditText edit;
	private ScrollView scrollview;
	private MyViewGroup myviewgroup;
	private Handler handler;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		initControl();
		
		/**
		 * 设置  回调接口
		 */
		myviewgroup.setMyViewGroupInterface(new MyViewGroupInterface() {
			@Override
			public void setScrollViewHeight(int scrollViewHeight,final boolean isAdd) {
				//设置 scrollview的高度  注意 scrollview 的父容器是哪个布局  下面的LayoutParams就应该选择对应的
				//如 scrollview的父容器是 LinearLayout 则下面应该用
//				final LinearLayout.LayoutParams rl = (android.widget.LinearLayout.LayoutParams) scrollview.getLayoutParams();
				final RelativeLayout.LayoutParams rl = (LayoutParams) scrollview.getLayoutParams();
				rl.height = scrollViewHeight;
				handler.post(new Runnable() {
					@Override
					public void run() {
						scrollview.setLayoutParams(rl);
						if(isAdd) //如果是添加 就要将 位置定位到最新添加的子view上
							scrollview.scrollBy(0, myviewgroup.getGroupViewheight());
					}
				});
			}
		});
		
	}

	/**
	 * 初始化控件
	 */
	private void initControl(){
		handler = new Handler();
		button = (Button) this.findViewById(R.id.button);
		edit = (EditText) this.findViewById(R.id.edit);
		scrollview = (ScrollView) this.findViewById(R.id.scrollview);
		myviewgroup = (MyViewGroup) this.findViewById(R.id.myviewgroup);
		button.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		switch(v.getId()){
		case R.id.button:
			String text = edit.getText().toString().trim();
			if(TextUtils.isEmpty(text)){
				Toast.makeText(this, "不能为空", Toast.LENGTH_SHORT).show();
				break;
			}
			addChildView(text);
			break;
		}
	}
	
	@SuppressLint("NewApi") 
	private void addChildView(String text)
	{
		final TextView tv = new TextView(this);
		tv.setText(text);
		tv.setSingleLine(true);
		tv.setTextSize(TypedValue.COMPLEX_UNIT_SP,12);
		tv.setMaxEms(6);
		tv.setTextColor(Color.BLACK);
		tv.setAlpha(0.5f);
		int dp = DpToPx.dip2px(this, 8);  
		tv.setPadding(dp,dp,dp,dp);
		tv.setBackgroundResource(R.drawable.text_style);
		tv.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				myviewgroup.removeView(tv);		//点击 删除 
			}
		});
		myviewgroup.addView(tv, myviewgroup.getChildCount());//添加
	}
	
}

MyViewGroup
public class MyViewGroup extends ViewGroup {

	
	public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public MyViewGroup(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public MyViewGroup(Context context) {
		super(context);
	}
	
	public void setMyViewGroupInterface(MyViewGroupInterface face)
	{
		this.face = face;
	}
	
	private int count;		//改变前的 子View数量
	private boolean isAdd; //判断 是添加还是删除
	private MyViewGroupInterface face;

	/**
	 * 计算 各个子View的位置
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
//		 if (!changed)
//			 return;
		int i = getChildCount();
		if(count == i)
			return;
		isAdd = true;
		if(count > i)		//改变前的子view数量 大于 当前的数量 表示 删除
			isAdd = false;
		count = i;
		int width = getMeasuredWidth();

		int childWidth = 0;
		int childHeight = 0;

		int totalWidth = leftSpacing + rightSpacing;
		int currentTopPosition = topSpacing;
		int currentLeftPosition = leftSpacing;
		
		int maxHeight = 0;
		for (int j = 0; j < i; j++) {
			View v = getChildAt(j);
			childWidth = v.getMeasuredWidth();
			childHeight = v.getMeasuredHeight();
			if (j == 0) {
				totalWidth += childWidth;
				maxHeight = childHeight;
			} else {
				totalWidth += (childWidth + left_Right_Spacing);
				if (totalWidth > width) {
					currentTopPosition += (maxHeight + top_Bottom_Spacing);
					currentLeftPosition = leftSpacing;
					maxHeight = childHeight;
					totalWidth = leftSpacing + rightSpacing + childWidth;
				} else {
					if (childHeight > maxHeight) {
						maxHeight = childHeight;
					}
					View upChild = getChildAt(j-1);
					int upChildWidth = upChild.getMeasuredWidth();
					currentLeftPosition += (upChildWidth + left_Right_Spacing);
				}
			}
			l = currentLeftPosition;
			t = currentTopPosition;
			r = childWidth + currentLeftPosition;
			b = currentTopPosition + childHeight;
			v.layout(l, t, r, b);
		}
		if(i == 0){
			if(face != null)
				face.setScrollViewHeight(0,isAdd);
		}else{
			if(face != null)
				face.setScrollViewHeight(scrollViewHeight,isAdd);
		}
		
	}

	private final int leftSpacing = 10; // 子View离父容器左边的距离
	private final int rightSpacing = 10;// 子View离父容器右边的距离
	private final int topSpacing = 8;// 子View离父容器上边的距离
	private final int bottomSpacing = 8;// 子View离父容器底边的距离
	private final int left_Right_Spacing = 10;// 两个子View左右之间的间隔
	private final int top_Bottom_Spacing = 10;// 两个子View上下之间的间隔
	private final int umberRows = 3;//父容器中能够窜下子View的最大行数
	private int groupHeight;
	private int scrollViewHeight;
	private int height,width;
	
	
	/**
	 * 计算 父容器的宽高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		// 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
		int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
		
		// 计算出所有的childView的宽和高
		measureChildren(widthMeasureSpec, heightMeasureSpec);
		width = sizeWidth;// ViewGroup 的宽
		height = topSpacing + bottomSpacing;// ViewGroup 的高

		int childCount = this.getChildCount();// 子View的总个数

		int childWidth = 0;// 子View的宽
		int childHeight = 0;// 子View的高

		int currentWidth = leftSpacing + rightSpacing;// 子View相加的 宽
		int currentHeight = 0;
		int row = 0;//子View的行数
		for (int i = 0; i < childCount; i++) {
			View childView = getChildAt(i);
			childWidth = childView.getMeasuredWidth();
			childHeight = childView.getMeasuredHeight();
			if (i == 0) {
				row++;
				currentWidth += childWidth;
				currentHeight = childHeight;
			} else {
				currentWidth += (childWidth + left_Right_Spacing);
			}
			if (currentWidth > width) {//当子View相加的宽大于父容器的宽时 自动换行 并重置currentWidth 和 currentHeight
				row++;
				currentWidth = leftSpacing + rightSpacing + childWidth;
				height += (currentHeight + top_Bottom_Spacing);
				currentHeight = childHeight;
			} else {
				if (childHeight > currentHeight) {
					currentHeight = childHeight;
				}
			}
			if(row <= umberRows)
			{
				scrollViewHeight = height+ currentHeight;
			}
		}
		height += currentHeight;
		groupHeight = height;
		Log.e("", "scrollViewHeight == "+scrollViewHeight);
		setMeasuredDimension(width, height);
	}
	
	public int getGroupViewheight()
	{
		return groupHeight;
	}
	

	@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
		new MarginLayoutParams(getContext(), attrs);
		return super.generateLayoutParams(attrs);
	}
	
	/**
	 * 改变 scrollview高度的 回调接口
	 * @author linxi
	 *
	 */
	public interface MyViewGroupInterface
	{
		public void setScrollViewHeight(int scrollViewHeight,boolean isAdd);
	}

}

DpToPx
public class DpToPx {

	/**
	 * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
	 */
	public static int dip2px(Context context, float dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}

	/**
	 * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
	 */
	public static int px2dip(Context context,float pxValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (pxValue / scale + 0.5f);
	}
	
     /**
      * 将px值转换为sp值,保证文字大小不变
      * 
      * @param pxValue
      * @param fontScale
      *            (DisplayMetrics类中属性scaledDensity)
      * @return
      */ 
     public static int px2sp(Context context, float pxValue) { 
         final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 
         return (int) (pxValue / fontScale + 0.5f); 
     } 
     
     /**
      * 将sp值转换为px值,保证文字大小不变
      * 
      * @param spValue
      * @param fontScale
      *            (DisplayMetrics类中属性scaledDensity)
      * @return
      */ 
     public static int sp2px(Context context, float spValue) { 
         final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 
         return (int) (spValue * fontScale + 0.5f); 
     }
     
}

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <View
        android:id="@+id/v"
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:layout_marginTop="10dp"
        android:background="#FF2525" />

    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_below="@+id/v"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp" >

        <com.example.adaptivewidthheightviewgroup.MyViewGroup
            android:id="@+id/myviewgroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.example.adaptivewidthheightviewgroup.MyViewGroup>
    </ScrollView>

    <View
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:layout_below="@+id/scrollview"
        android:background="#195794" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        android:paddingBottom="10dp"
        android:paddingTop="10dp" >

        <EditText
            android:id="@+id/edit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/input_content"
            android:inputType="text"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="5dp"
            android:textColor="#000000"
            android:textSize="18sp" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="@string/add"
            android:textColor="#000000"
            android:textSize="18sp" />
    </LinearLayout>

</RelativeLayout>

  

有需要 源码的 朋友 可以 在评论里面写邮箱 ,看到我会发给你。

 


  


  

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。