zoukankan      html  css  js  c++  java
  • 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>
    

      

    有需要 源码的 朋友 可以 在评论里面写邮箱 .

    
    

      


      

  • 相关阅读:
    [luogu4799 CEOI2015 Day2] 世界冰球锦标赛(折半搜索)
    [luogu3230 HNOI2013] 比赛 (搜索+Hash)
    [luogu2317 HNOI2005] 星际贸易 (dp)
    [luogu2414 NOI2011]阿狸的打字机 (AC自动机)
    [bzoj3507 Cqoi2014]通配符匹配 (hash+DP)
    [luogu2054 AHOI2005] 洗牌 (数论)
    bzoj1491 [NOI2007]社交网络
    bzoj1022 [SHOI2008]小约翰的游戏John
    bzoj1088 [SCOI2005]扫雷Mine
    bzoj1295 [SCOI2009]最长距离
  • 原文地址:https://www.cnblogs.com/linxi130126/p/4435247.html
Copyright © 2011-2022 走看看