【Android-view】listView 每個item里動態添加不定量的控件,Android 自動換行


問題描述:

  開發過程中,遇到了在listview里面的每個item都有可能顯示圖片,並且需要顯示的圖片的數量不確定,需要自動換行。

如圖:第一行顯示三張圖片,第二行顯示四張圖片。數量0---正無窮(內存支持的情況下)

解決辦法:

  最初就是直接從網上找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); } }

 

 

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

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM