問題描述:
開發過程中,遇到了在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); } }
至此,就就結束了,希望可以幫到一部分人。