很多时候 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>
有需要 源码的 朋友 可以 在评论里面写邮箱 ,看到我会发给你。
时间: 2024-10-28 14:41:19