1. 程式人生 > >ScrollView巢狀Viewpager巢狀ListView時遇到的問題

ScrollView巢狀Viewpager巢狀ListView時遇到的問題

問題彙總:

1.介面顯示不全,並且需要將TabLayout跟隨ListView往上移動

2.當滑動Viewpager時ListView會突然跳到螢幕的頂部

3.當內容往上滑動,使TabLayout懸浮在頂部

問題一

問題描述:.介面顯示不全,需要將TabLayout跟隨ListView往上移動

解決問題的思路,首先獲取ListView的整個控制元件的高度Height,設定外層Viewpager的高度為Height.這樣Scrollview就能完全顯示介面.

解決方案: 

第一步:計算listview高度

使用工具類測量
public class ViewUtil {
    public static void 
setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null,
listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } /** * 獲取Listview
的高度,然後設定ViewPager的高度 * @param listView * @return */ public static int setListViewHeightBasedOnChildren1(ListView listView) { //獲取ListView對應的Adapter ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return 0; } int totalHeight = 0; for (int i = 0, len = listAdapter.getCount(); i < len; i++) { //listAdapter.getCount()返回資料項的數目 View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); //計運算元項View 的寬高 totalHeight += listItem.getMeasuredHeight(); //統計所有子項的總高度 } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); //listView.getDividerHeight()獲取子項間分隔符佔用的高度 //params.height最後得到整個ListView完整顯示需要的高度 listView.setLayoutParams(params); return params.height; } }
使用EventBus把測量的高度回傳給Viewpager所在的activity(fragment)
listViewHomeVPAdapter = new ListViewHomeVPAdapter(getContext(),data);
mListView.setAdapter(listViewHomeVPAdapter);
int listViewHeight = ViewUtil.setListViewHeightBasedOnChildren1(mListView);
EventBus.getDefault().post(new ListViewHeight(listViewHeight)); 
 給Viewpager設定Height
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(ListViewHeight listViewHeight) {

    int height = listViewHeight.getListViewHeight();
ViewGroup.LayoutParams layoutParams = mViewPager.getLayoutParams();
layoutParams.height = height;mViewPager.setLayoutParams(layoutParams);
}
現在解決了介面顯示不全的問題.
第二步:自定義ScrollView
public class MyScrollView extends ScrollView {
    private float xDistance, yDistance, xLast, yLast;
    private OnScrollListener onScrollListener;
/**
     * 主要是用在使用者手指離開MyScrollViewMyScrollView還在繼續滑動,我們用來儲存Y的距離,然後做比較
*/
private int lastScrollY;
    public MyScrollView(Context context) {
        this(context, null);
}

    public MyScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
}

    public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
}

    /**
     * 設定滾動介面
* @param onScrollListener
*/
public void setOnScrollListener(OnScrollListener onScrollListener) {
        this.onScrollListener = onScrollListener;
}

    /**
     * 用於使用者手指離開MyScrollView的時候獲取MyScrollView滾動的Y距離,然後回撥給onScroll方法中
*/
private Handler handler = new Handler() {

        public void handleMessage(android.os.Message msg) {
            int scrollY = MyScrollView.this.getScrollY();
//此時的距離和記錄下的距離不相等,在隔5毫秒給handler傳送訊息
if(lastScrollY != scrollY){
                lastScrollY = scrollY;
handler.sendMessageDelayed(handler.obtainMessage(), 5);
}
            if(onScrollListener != null){
                onScrollListener.onScroll(scrollY);
}

        }

    };
/**
     * 重寫onTouchEvent, 當用戶的手在MyScrollView上面的時候,
* 直接將MyScrollView滑動的Y方向距離回撥給onScroll方法中,當用戶擡起手的時候,
* MyScrollView可能還在滑動,所以當用戶擡起手我們隔5毫秒給handler傳送訊息,在handler處理
* MyScrollView滑動的距離
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
        if(onScrollListener != null){
            onScrollListener.onScroll(lastScrollY = this.getScrollY());
}
        switch(ev.getAction()){
            case MotionEvent.ACTION_UP:
                handler.sendMessageDelayed(handler.obtainMessage(), 5);
                break;
}

        Log.d("print", "getScrollY: "+this.getScrollY());
        return super.onTouchEvent(ev);
}


    /**
     *
     * 滾動的回撥介面
*
     */
public interface OnScrollListener{
        /**
         * 回撥方法, 返回MyScrollView滑動的Y方向距離
*/
public void onScroll(int scrollY);
}

    /**
     *解決ViewPagerScrollView手勢衝突的問題
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float curX = ev.getX();
                final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
                if(xDistance > yDistance){
                    return false;
}
        }
        return super.onInterceptTouchEvent(ev);
}

}
最外層的ScrollView改成使用自定義的MyScrollView

問題二:

問題描述:

在專案中用到了ScrollView巢狀ViewPager巢狀ListView情況,當滑動Viewpager時ListView會突然跳到螢幕的頂部

解決方案:

在Fragment之外的控制元件中新增3個屬性

在ScrollView的根佈局中新增屬性設定

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants">
關鍵程式碼:
    android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"

屬性是當一個為View獲取焦點時,定義ViewGroup和其子控制元件兩者之間的關係.

descendantFocousability屬性的值有三種: beforeDescendants , afterDescendants , blocksDescendants.

beforeDescendants: ViewGroup會優先其子控制元件獲取焦點.

afterDescendants: ViewGroup只有當他的子控制元件不需要獲取焦點時才獲取焦點.

blocksDescendants: ViewGroup會覆蓋子類控制元件而直接獲得焦點.

問題三:

問題描述:.當內容往上滑動,使TabLayout懸浮在頂部 需要實現的效果:
解決思路:在XML檔案中放置兩個RelativeLayout,  一個保持在原位置,一個在頂部佔位(當需要的時候把TabLayout新增進去)
解決方案:
ViewPager所在的Activity(Fragment)中
MyScrollViewHomeFragment.setOnScrollListener(this);

@Override
public void onScroll(int scrollY) {
    if (scrollY >= 600) {
        if (mTabFragmentHome.getParent() != relativeLayoutTop) {
            relativeLayoutCenter.removeView(mTabFragmentHome);
relativeLayoutTop.addView(mTabFragmentHome);
}
    } else {
        if (mTabFragmentHome.getParent() != relativeLayoutCenter) {
            relativeLayoutTop.removeView(mTabFragmentHome);
relativeLayoutCenter.addView(mTabFragmentHome);
}
    }
}

佈局檔案(此處有修改,請按照思路模仿)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
    <com.xxx.widget.MyScrollView
android:id="@+id/MyScrollView_home_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
        <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true">
            <android.support.v4.view.ViewPager
android:id="@+id/vp_fragment_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/relativeLayout_center" />
            <RelativeLayout
android:id="@+id/relativeLayout_center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/GongNeng">
                <android.support.design.widget.TabLayout
android:id="@+id/tab_fragment_home"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#fff"
app:tabIndicatorColor="@color/primary"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/color_text_selected"
app:tabTextColor="@color/color_text_normal" />
            </RelativeLayout>
        </RelativeLayout>
    </com.xxx.widget.MyScrollView>
    <RelativeLayout
android:id="@+id/relativeLayout_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>

相關推薦

ScrollViewViewpagerListView遇到的問題

問題彙總: 1.介面顯示不全,並且需要將TabLayout跟隨ListView往上移動 2.當滑動Viewpager時ListView會突然跳到螢幕的頂部 3.當內容往上滑動,使TabLayout懸浮在頂部 問題一 問題描述:.介面顯示不全,需要將TabLayout跟隨

fragment中 ScrollView 同時viewpager banner和 listviewscrollview 滑動異常·

fragment中 ScrollView                      同時巢狀viewpager banner和        &nbs

RecyclerView裡ViewPager,滾動RecyclerView,記住之前ViewPager滑動後的位置

如果是ListView裡巢狀ViewPager的話,首先要考慮的是豎向滑動和橫向衝突的問題,RecyclerView的話,不用考慮此問題 方法: 準備一個map來儲存你滑動過的ViewPager所在的RcyclerView中的位置和你滑動Vie

Android 仿京東,淘寶RecyclerViewViewPagerRecyclerView商品展示

最近看到京東,淘寶都有RecyclerView巢狀ViewPager巢狀RecyclerView商品展示的效果,效果挺好,廢話不多說先看效果圖: GIF.gif 技能點: 1.Android事件分發機制等 需求點: 1.列表巢狀,內層的列表可以左右切換 2.V

ListView顯示不全,ViewPager顯示不全,ScrollVIewViewPager顯示問題

自定義listView,重寫他的onMeasure方法:解決listView顯示不全 @Overrideprotected void onMeasure(int widthMeasureSpec,

ScrollViewListView禁止ListView的滾動

ScrollView內巢狀ListView時不知道為什麼ListView高度很小隻能顯示一行資料,網上有說是因為ScrollView和ListView之間衝突導致的 禁止ListView的滾動事件時可以解決該問題,只讓

解決ScrollView或者listviewViewPager 時候 Pager左右滑動不流暢

pager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) {

ScrollViewListView,需要根據內容來設定listView的高度

動態設定ListView的高度 public void setListViewHeightBasedOnChildren(ListView mListView) { ListAdapter listAdapter = mListView.getAdapter();

解決ScrollViewviewPagerlistView滑動事件衝突問題(水平方向)

我們在開發中經常會碰到view滑動衝突的情況。滑動衝突的解決辦法就兩種:1.外部攔截法:是指在點選事件先經過父容器的攔截處理,如果父容器需要處理此事件就進行攔截,如果不需要此事件就不攔截,這樣就可以解決滑動衝突的問題,外部攔截法需要重寫父容器的onInterceptTouch

Android學習 之 問題&解答 ScrollViewListView顯示不全的簡便解決方案

利用下面這個Utility 類的靜態方法setListViewHeightBasedOnChildren()即可實現: 在listview.setAdapter()之後呼叫Utility.setListViewHeightBasedOnChilren(listview)就

安卓在ScrollViewViewPager,設定ViewPager的單個頁面高度隨內容變化

在開發過程中,有時候頁面佈局比較複雜,會使用到ScrollView和ViewPager,如果不進行處理,會出現不顯示ViewPager的子頁面,或者子頁面高度一樣,內容顯示不全,或者是留白太多。我的需求是需要在頁面下面加一個可以左右滑動的分欄,而且兩個分類的頁面高度不一致且不

解決Android中ScrollViewlistviewlistview不能不能滾動的問題

       我們在Android的佈局中有時會使用到ScrollView,然後在ScrollView中再巢狀listview,但是這樣就會導致listview獲取焦點失敗不能滾動(具體原理可自行搜尋Android的觸控事件的分發機制),在搜尋解決方案時發現需要重寫Scrol

ScrollViewListViewBug解決以及ExpandableListView設定全部展開

1.ExpandableListView設定預設展 mExpandListview.setAdapter(adapter); //設定ExpandableListView全部展開 for (int i = 0;i < adapter.getGroupCount();

scrollviewviewpager(fragment裡有listview

專案地址: 經常用到scrollview巢狀listview, 效果是:listview自己不滾動,隨著scrollview的滾動而滾動。 但是有個需求是scrollview巢狀viewpager,viewpager有三個fragment,fragme

Android:ScrollViewViewPagerListView示例

引言: 我們在實際開發一個款Android App時,經常會遇到Scrollview和ViewPager和ListView同時使用的場景,如下圖所示的需求: 下面我們通過程式碼來模擬一下這種場景: 佈局檔案: <?xml version="

解決ScrollViewRecyclerView(橫向)或ListView(橫向),橫向滑動不順暢的問題。

程式碼簡單,容易理解,裡面有點註釋,夠看了,特別少的改動。 package com.laka.live.ui.widget; import android.content.Context; im

從原始碼角度解析 - ScrollViewViewPager不顯示的問題

<ScrollView android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="match_parent">

Android---SwipeRefreshLayoutViewPager的滑動衝突

SwipeRefreshLayout巢狀ViewPager 最近在專案中用到了SwipeRefreshLayout控制元件,以實現下拉重新整理,在我的SwipeRefreshLayout佈局中存在一個ViewPager。那麼問題就出現了,當我對ViewPager

scrollviewviewpager不顯示

activityScdetailsBottomVp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {              @Override            publicvoid onPageS

Android 混排效果之 ScrollView RecyclerView gridview 實現listview gridview 效果

RecyclerView 出現以後 很受大家歡迎 漂亮流暢的列表 簡單的操作 可以幫我們完成很多的列表 但是有一種listview 巢狀gridview 的效果 目前還是需要巢狀才能完成 現在就簡單說一下我的思路 本人的需求是例如手機淘寶頁 本人使用老套的實現模