很多时候 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>
有需要 源码的 朋友 可以 在评论里面写邮箱 .