如圖 :緩存
出現的問題截圖如上,當只有一個圖標時GridView的寬度(灰色區域)也是match_parent的,這個時候點擊gridview區域是ListView是不能響應的,可是若是GridView的背景色與ListView的背景一致,用戶是看不到GridView的寬度,當用戶點擊圖片之外的區域,可能的操做就是進入到該條消息的詳情頁,可是因爲此時GridView是match_parent的,因此ListView根本不會獲取到點擊事件,這樣的體驗很很差。咱們須要的效果是這樣的 :app
即GridView的大小恰好可以包含圖片的大小,這樣當GridView的背景色爲默認時,用戶點擊圖片之外的區域就是點擊了ListView的Item。ide
咱們看看如何解決這個問題吧,首先佈局方面就不講了,主要仍是講講GridView的寬高問題吧。解決GridView的高度問題,須要覆寫GridView的onMeasure方法,代碼以下 :佈局
public class MGridView extends GridView { public boolean hasScrollBar = true; /** * @param context */ public MGridView(Context context) { this(context, null); } public MGridView(Context context, AttributeSet attrs) { super(context, attrs, 0); } public MGridView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = heightMeasureSpec; if (hasScrollBar) { expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec);// 注意這裏,這裏的意思是直接測量出GridView的高度 } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } }
在onMeasure方法中,由於hasScrollBase爲true, 咱們會注意到代碼中有註釋的分支。這裏實際上就是在onMeasure的時候計算出GridView的高度,而不是隻計算其中幾個View的高度。若是沒有這一步,那麼GridView的高度將顯示不全。將GridView的高度計算出來,這樣就不須要上下滑動來顯示其它的item了,由於問題所在就是GridView嵌套在了ScrollView或者包含ScrollView的組件中,從而引起的衝突。this
下面解決寬度的問題,思路就是在ListView的getView方法中手動計算每一個GridView的圖片個數,若是圖片個數小於GridView每行的列數,則手動計算每一個child view所需的寬度,而後GridView的寬度 = child個數 * 每一個child view的寬度。爲了不重複計算,咱們會緩存計算結果。計算代碼以下 :code
/** * @author mrsimple */ public final class GridViewUtils { /** * 存儲寬度 */ static SparseIntArray mGvWidth = new SparseIntArray(); /** * 計算GridView的高度 * * @param gridView 要計算的GridView */ public static void updateGridViewLayoutParams(MGridView gridView, int maxColumn) { int childs = gridView.getAdapter().getCount(); if (childs > 0) { int columns = childs < maxColumn ? childs % maxColumn : maxColumn; gridView.setNumColumns(columns); int width = 0; int cacheWidth = mGvWidth.get(columns); if (cacheWidth != 0) { width = cacheWidth; } else { // 計算gridview每行的寬度, 若是item小於3則計算全部item的寬度; // 不然只計算3個child寬度,所以一行最多3個child。 (這裏咱們以3爲例) int rowCounts = childs < maxColumn ? childs : maxColumn; for (int i = 0; i < rowCounts; i++) { View childView = gridView.getAdapter().getView(i, null, gridView); childView.measure(0, 0); width += childView.getMeasuredWidth(); } } ViewGroup.LayoutParams params = gridView.getLayoutParams(); params.width = width; gridView.setLayoutParams(params); if (mGvWidth.get(columns) == 0) { mGvWidth.append(columns, width); } } }
ListView的getView方法以下 :事件
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.listview_item, parent, false); viewHolder = new ViewHolder(); viewHolder.mGridView = (MGridView) convertView.findViewById(R.id.my_gridview); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_tv); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } final ListViewItem item = getItem(position); // 設置GridView的Adapter viewHolder.mGridView.setAdapter(new GridViewAdapter(mContext, item.mImages)); // 計算GridView寬度, 設置默認爲numColumns爲3. GridViewUtils.updateGridViewLayoutParams(viewHolder.mGridView, 3); viewHolder.mTextView.setText(item.mText); return convertView; }
這樣,咱們就解決了消息流的寬高問題。圖片
最近在運營一個有關反脆弱成長的我的公衆號,歡迎關注get