[转载]Android-view listView 每个item里动态添加不定量的控件,Android 自动换行 - helloworld.MR-zz - 博客园

[转载]【Android-view】listView 每个item里动态添加不定量的控件,Android 自动换行 – helloworld.MR-zz – 博客园.

问题描述:

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

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

解决办法:

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

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

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

具体解决办法如下:

a.修改values下attrs.xml文件

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

<resources>
    <declare-styleable name="FlowLayout">
        <attr name="horizontalSpacing" format="dimension" />
        <attr name="verticalSpacing" format="dimension" />
        <attr name="numColumns" format="integer" /><!--这个属性为新加的-->
    </declare-styleable>
    <declare-styleable name="FlowLayout_LayoutParams">
        <attr name="layout_breakLine" format="boolean" />
        <attr name="layout_horizontalSpacing" format="dimension" />
    </declare-styleable>
</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方法,由于对这块还不太了解,所以只是简单的改了一下,测试之后效果是实现了,暂未发现其他问题。应该还有更好的解决方案,希望有人指正。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight();
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED;

        int width = 0;
        int height = getPaddingTop();

        int currentWidth = getPaddingLeft(); 
        int currentHeight = 0;               

        boolean breakLine = false;
        boolean newLine = false;
        int spacing = 0;

        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);

            LayoutParams lp = (LayoutParams) child.getLayoutParams();
            spacing = mHorizontalSpacing;
            if (lp.horizontalSpacing >= 0) {
                spacing = lp.horizontalSpacing;
            }

            if (growHeight && (i == numColumns||breakLine || currentWidth + child.getMeasuredWidth() > widthSize)) {
//                newLine = true;
                
                height += currentHeight + mVerticalSpacing;
                width = Math.max(width, currentWidth - spacing);
                
                currentHeight = 0;
                currentWidth = getPaddingLeft();
                
            }
//            else {
//                newLine = false;
//            }
            if (i>numColumns&&i%numColumns==0) {//主要修改的是这个判断语句,原版的判断语句是29,38,39,40行的被隐掉的。我自己用原版的判断语句有问题,
                newLine = false;
            }

            lp.x = currentWidth;
            lp.y = height;

            currentWidth += child.getMeasuredWidth() + spacing;
            currentHeight = Math.max(currentHeight, child.getMeasuredHeight());
            
            breakLine = lp.breakLine;
        }

        if (!newLine) {
            height += currentHeight;
            width = Math.max(width, currentWidth - spacing);
        }

        width += getPaddingRight();
        height += getPaddingBottom();

        setMeasuredDimension(resolveSize(width, widthMeasureSpec),
                resolveSize(height, heightMeasureSpec));
    }

至此,就修改完毕了。

具体使用办法如下。

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:f="http://schemas.android.com/apk/res/你的androidmanifest.xml文件中的package属性值"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
     >

   
        <com.xingyunhudong.view.FlowLayout
            android:id="@+id/flowlaytou"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
           f:numColumns="3"<!--也可以不指定,如果不指定,在FrameLayout的构造函数里,默认取值为3列-->
             >
        </com.xingyunhudong.view.FlowLayout>

        

</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); } }

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

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏