【Android-view】listView 每个item里动态添加不定量的控件,Android 自动换行

问题描述:

  开发过程中,遇到了在listview里面的每个item都有可能显示图片,并且需要显示的图片的数量不确定,需要自动换行。

如图:第一行显示三张图片,第二行显示四张图片。数量0---正无穷(内存支持的情况下)

【Android-view】listView 每个item里动态添加不定量的控件,Android 自动换行

解决办法:

  最初就是直接从网上找Android自动换行的控件,再此感谢eoe论坛里**dahege **分享的源码。

  dahege eoe论坛原文地址:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=195276

  但是我直接拿来用的时候出现了个问题,就是当有四张图片的时候只显示三行。

  具体解决办法如下:

  a.修改values下attrs.xml文件

    增加一个每行显示多少列的属性,类似gridview 

 1 <resources>

 2     <declare-styleable name="FlowLayout">

 3         <attr name="horizontalSpacing" format="dimension" />

 4         <attr name="verticalSpacing" format="dimension" />

 5         <attr name="numColumns" format="integer" /><!--这个属性为新加的-->

 6     </declare-styleable>

 7     <declare-styleable name="FlowLayout_LayoutParams">

 8         <attr name="layout_breakLine" format="boolean" />

 9         <attr name="layout_horizontalSpacing" format="dimension" />

10     </declare-styleable>

11 </resources>

 

  b.修改FlowLayout.java 源文件

    1.在构造方法里得到用户在cml文件里设置的numColumns

    public FlowLayout(Context context, AttributeSet attrs) {

        super(context, attrs);

        

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);

        try {

            mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);

            mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);

            numColumns = a.getInt(R.styleable.FlowLayout_numColumns, 3);//得到用户在布局文件中设置的没行显示的列数

        } finally {

            a.recycle();

        }

        

        mPaint = new Paint();

        mPaint.setAntiAlias(true);

        mPaint.setColor(0xffff0000);

        mPaint.setStrokeWidth(2.0f);

    }

 

    2.修改onMeasure方法,由于对这块还不太了解,所以只是简单的改了一下,测试之后效果是实现了,暂未发现其他问题。应该还有更好的解决方案,希望有人指正。

 1 @Override

 2     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

 3         int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();

 4         int widthMode = MeasureSpec.getMode(widthMeasureSpec);

 5         boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;

 6 

 7         int width = 0;

 8         int height = getPaddingTop();

 9 

10         int currentWidth = getPaddingLeft(); 

11         int currentHeight = 0;               

12 

13         boolean breakLine = false;

14         boolean newLine = false;

15         int spacing = 0;

16 

17         final int count = getChildCount();

18         for (int i = 0; i < count; i++) {

19             View child = getChildAt(i);

20             measureChild(child, widthMeasureSpec, heightMeasureSpec);

21 

22             LayoutParams lp = (LayoutParams) child.getLayoutParams();

23             spacing = mHorizontalSpacing;

24             if (lp.horizontalSpacing >= 0) {

25                 spacing = lp.horizontalSpacing;

26             }

27 

28             if (growHeight && (i == numColumns||breakLine || currentWidth + child.getMeasuredWidth() > widthSize)) {

29 //                newLine = true;

30                 

31                 height += currentHeight + mVerticalSpacing;

32                 width = Math.max(width, currentWidth - spacing);

33                 

34                 currentHeight = 0;

35                 currentWidth = getPaddingLeft();

36                 

37             }

38 //            else {

39 //                newLine = false;

40 //            }

41             if (i>numColumns&&i%numColumns==0) {//主要修改的是这个判断语句,原版的判断语句是29,38,39,40行的被隐掉的。我自己用原版的判断语句有问题,

42                 newLine = false;

43             }

44 

45             lp.x = currentWidth;

46             lp.y = height;

47 

48             currentWidth += child.getMeasuredWidth() + spacing;

49             currentHeight = Math.max(currentHeight, child.getMeasuredHeight());

50             

51             breakLine = lp.breakLine;

52         }

53 

54         if (!newLine) {

55             height += currentHeight;

56             width = Math.max(width, currentWidth - spacing);

57         }

58 

59         width += getPaddingRight();

60         height += getPaddingBottom();

61 

62         setMeasuredDimension(resolveSize(width, widthMeasureSpec),

63                 resolveSize(height, heightMeasureSpec));

64     }

 

至此,就修改完毕了。

具体使用办法如下。

a.在listview的item布局文件中使用framelayout自定义控件

1 <?xml version="1.0" encoding="utf-8"?>

 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

 3     xmlns:f="http://schemas.android.com/apk/res/你的androidmanifest.xml文件中的package属性值"

 4     android:layout_width="fill_parent"

 5     android:layout_height="wrap_content"

 6      >

 7 

 8    

 9         <com.xingyunhudong.view.FlowLayout

10             android:id="@+id/flowlaytou"

11             android:layout_width="fill_parent"

12             android:layout_height="wrap_content"

13             android:layout_marginTop="8dp"

           f:numColumns="3"<!--也可以不指定,如果不指定,在FrameLayout的构造函数里,默认取值为3列-->



14              >

15         </com.xingyunhudong.view.FlowLayout>

16 

17         

18 

19 </LinearLayout>

 

b.在adapter中设值

public class XXXAdapterextends BaseAdapter {



    private LayoutInflater inflater;

    private List<XXX> xxxList;

    private Context context;



    private ViewGroup.LayoutParams paramsImg, paramsVideo;

    private int sw;



    public HuaTiAdapter(Context context, List<xxx> xxxList) {

        this.xxxList = xxxList;

        this.context = context;

        inflater = (LayoutInflater) context

                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        sw = CommonUtils.getScreenWidth((Activity) context);

        int w = context.getResources().getDimensionPixelSize(

                R.dimen.xxx_img_total_width);

        sw = sw - w;

        paramsImg = new ViewGroup.LayoutParams(sw / 3, sw / 3);

        paramsVideo = new ViewGroup.LayoutParams(sw, 0);//为了图片适配

    }



    @Override

    public int getCount() {

        // TODO Auto-generated method stub

        return xxxList.size();

    }



    @Override

    public Object getItem(int position) {

        // TODO Auto-generated method stub

        return xxxList.get(position);

    }



    @Override

    public long getItemId(int position) {

        // TODO Auto-generated method stub

        return position;

    }



    class ViewHolder {

        FlowLayout ll;

        int flag;

    }



    @Override

    public View getView(int position, View convertView, ViewGroup parent) {

        // TODO Auto-generated method stub

        ViewHolder holder = null;

        xxxBean huati = xxxList.get(position);

        if (convertView == null

                || ((ViewHolder) convertView.getTag()).flag != position) {//第一个判断是优化listview加载速度及内存消耗,第二个判断是为了防止图片错位

            holder = new ViewHolder();

            holder.flag = position;

            convertView = inflater.inflate(R.layout.xxx_item_layout, null);

            

            holder.ll = (FlowLayout) convertView.findViewById(R.id.flowlaytou);

            ImageBean video = xxx.getVideoImg();

            if (video != null && video.getUrl() != null

                    && !"".equals(video.getUrl().trim())) {

                paramsVideo.height = video.getHeight() * sw / video.getWidth();

                addVideoView(holder.ll, video.getUrl(), paramsVideo, inflater);

            }

            List<ImageBean> imgList = huati.getImgList();

            if (imgList != null && imgList.size() > 0) {

                for (int i = 0; i < imgList.size(); i++) {

                    addImageView(holder.ll, imgList.get(i).getUrl(), paramsImg,

                            inflater, imgList, i);

                }

            }

            convertView.setTag(holder);

        } else {

            holder = (ViewHolder) convertView.getTag();

        }



        return convertView;

    }



    private void addVideoView(FlowLayout ll, final String url,

            LayoutParams params, LayoutInflater inflater) {

        ImageView v = (ImageView) inflater.inflate(

                R.layout.yyy_image_layout, null);//这个layout里面就只有一个imageview空间,特别简单

        v.setLayoutParams(params);

        ImageUtil.display(url, v);

        v.setOnClickListener(new OnClickListener() {



            @Override

            public void onClick(View v) {

                // TODO Auto-generated method stub

                //这里的点击事件也完全没有问题,不会错位,不会点击失效

            }

        });

        ll.addView(v);



    }



    private void addImageView(FlowLayout ll, String url, LayoutParams params,

            LayoutInflater inflater) {

        // TODO Auto-generated method stub

        ImageView v = (ImageView) inflater.inflate(

                R.layout.weixiu_image_layout, null);

        v.setLayoutParams(params);

        ImageUtil.display(url, v);

        v.setOnClickListener(new OnClickListener() {



            @Override

            public void onClick(View v) {

                // TODO Auto-generated method stub
                //这里的点击事件也完全没有问题,不会错位,不会点击失效
 } }); ll.addView(v); } }

 

 

至此,就就结束了,希望可以帮到一部分人。

 

 

 

 

 

 

你可能感兴趣的:(ListView)