Android中ListView嵌套GridView的簡單訊息流程UI(解決寬高問題)

來源:互聯網
上載者:User

標籤:

最近搞一個項目,需要用到類似於新浪微博的訊息流程,即每一項有文字、有九宮格圖片,因此這就涉及到ListView或者ScrollView嵌套GridView的問題。其中GridView的高度問題在網上都很容易找到答案,即覆寫onMeasure方法,然後設定高度的MeasureSpec。但是寬度問題確實沒有什麼資料,這裡所說的寬度問題是比如GridView的列數為3,那麼即使只有一張圖片,gridview的寬度也是match_parent的,導致使用者點擊在圖片範圍外但是在gridview範圍內時ListView的點擊事件不能捕獲。

:

出現的問題如上,當只有一個表徵圖時GridView的寬度(灰色地區)也是match_parent的,這個時候點擊gridview地區是ListView是不能響應的,但是如果GridView的背景色與ListView的背景一致,使用者是看不到GridView的寬度,當使用者點擊圖片以外的地區,可能的操作就是進入到該條訊息的詳情頁,但是由於此時GridView是match_parent的,所以ListView根本不會擷取到點擊事件,這樣的體驗很不好。我們需要的效果是這樣的 :

即GridView的大小剛好能夠包含圖片的大小,這樣當GridView的背景色為預設時,使用者點擊圖片以外的地區就是點擊了ListView的Item。

我們看看如何解決這個問題吧,首先布局方面就不講了,主要還是講講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的組件中,從而引發的衝突。

下面解決寬度的問題,思路就是在ListView的getView方法中手動計算每個GridView的圖片個數,如果圖片個數小於GridView每行的列數,則手動計算每個child view所需的寬度,然後GridView的寬度 = child個數 * 每個child view的寬度。為了避免重複計算,我們會緩衝計算結果。計算代碼如下 :

/** * @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方法如下 :

@Overridepublic 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;}

這樣,我們就解決了訊息流程的寬高問題。

Android中ListView嵌套GridView的簡單訊息流程UI(解決寬高問題)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.