1. 程式人生 > >scrollview巢狀viewpager(fragment裡有listview)

scrollview巢狀viewpager(fragment裡有listview)

專案地址:

經常用到scrollview巢狀listview,
效果是:listview自己不滾動,隨著scrollview的滾動而滾動。

但是有個需求是scrollview巢狀viewpager,viewpager有三個fragment,fragment裡有listview。

MainActivity佈局

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" tools:context="example.com.myvplvsv.MainActivity">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation
="vertical">
<TextView android:layout_width="match_parent" android:layout_height="100dp" android:layout_gravity="center" android:gravity="center" android:text="Hello World!" android:textColor="@color/colorAccent" android:textSize
="25sp" />
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#e9e9e9" android:orientation="vertical"> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginTop="12dp"> <TextView android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="@string/tab1" android:textColor="#cccccc" android:textSize="10sp" /> <TextView android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="@string/tab2" android:textColor="#cccccc" android:textSize="10sp" /> <TextView android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="@string/tab3" android:textColor="#cccccc" android:textSize="10sp" /> </LinearLayout> <View android:id="@+id/cursor" android:layout_width="150dp" android:layout_height="3dp" android:background="#ff7012" /> </LinearLayout> <example.com.myvplvsv.view.ViewPagerForScrollView android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ff4081" /> </LinearLayout> </ScrollView>

知識點:

1、動畫改變字型大小: tab2.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
2、佈局管理器的使用改變view的位置、大小等
3、viewpager的addOnPageChangeListener監聽。

參考:

MainActivity:


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int TAB_COUNT = 3;
    private TextView tab1;
    private TextView tab2;
    private TextView tab3;
    private ViewPager mVp;

    private int offset = 0;//初始位置
    private View cursor;
    private int scrollWidth;
    private int currentIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViews();

        setListener();

        initVp();

        initTabs();
    }

    private void setListener() {
        tab1.setOnClickListener(this);
        tab2.setOnClickListener(this);
        tab3.setOnClickListener(this);
    }

    private void findViews() {
        tab1 = (TextView) findViewById(R.id.tab1);
        tab2 = (TextView) findViewById(R.id.tab2);
        tab3 = (TextView) findViewById(R.id.tab3);
        cursor = findViewById(R.id.cursor);
        mVp = ((ViewPager) this.findViewById(R.id.vp));
    }

    private void initTabs() {
        //將頂部文字恢復預設值
        setTabsColor(tab1);
        tab1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(0);//設定時長為0

        //螢幕寬度
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenW = dm.widthPixels;

        //指示器滾動間隔
        scrollWidth = screenW / 3;
        //指示器寬度設定
        int cursorWidth = (screenW / 6);
        //指示器初始位置
        offset = (screenW / TAB_COUNT - cursorWidth) / 2;

        //佈局管理器使用方法一:
//        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(cursor.getLayoutParams());
//        layoutParams.width = cursorWidth;
//        layoutParams.setMargins(offset, 0, 0, 0);
//        cursor.setLayoutParams(layoutParams);

        //佈局管理器使用方法二:
        LinearLayout.LayoutParams cursorLayoutParams = (LinearLayout.LayoutParams) cursor.getLayoutParams();
        cursorLayoutParams.width = cursorWidth;
        cursorLayoutParams.leftMargin = offset;
        cursor.setLayoutParams(cursorLayoutParams);
    }

    private void initVp() {
        ArrayList<Fragment> fragmentLists = new ArrayList<>();
        fragmentLists.add(new Fragment1());
        fragmentLists.add(new Fragment2());
        fragmentLists.add(new Fragment3());
        FragmentManager fragmentManager = getSupportFragmentManager();

        mVp.setFocusable(false);
        mVp.setAdapter(new MyAdapter(fragmentManager, fragmentLists));
        mVp.setOffscreenPageLimit(2);
        mVp.setCurrentItem(0);
        mVp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                switch (position) {
                    //成功左滑一頁(0到1):
                    // onPageScrolled執行,positionOffset從0開始變大,此時position=0,currentIndex=0
                    // onPageSelected執行:currentIndex變為1,此時position=0,currentIndex=1
                    // onPageScrolled繼續執行,positionOffset從0開始變大直到無限接近1,此時position=0,currentIndex=1
                    // 最後onPageScrolled繼續執行,positionOffset從無限接近1突然恢復到0,此時position=1,currentIndex=1
                    case 0:
                        if (currentIndex == 0) {
                            setIndicatorPosition(offset + (int) (scrollWidth * positionOffset));
                            Log.e("000", "0-->currentIndex == 0");
                        } else if (currentIndex == 1) {
                            setIndicatorPosition(offset + (int) (scrollWidth * (positionOffset)));
                            Log.e("000", "0-->currentIndex == 1");
                        }
                        break;

                    case 1:
                        if (currentIndex == 1) {
                            setIndicatorPosition(offset + scrollWidth + (int) (scrollWidth * positionOffset));
                            Log.e("000", "1-->currentIndex == 1");
                        } else if (currentIndex == 2) {
                            setIndicatorPosition(offset + scrollWidth + (int) (scrollWidth * (positionOffset)));
                            Log.e("000", "1-->currentIndex == 2");
                        }
                        break;

                    case 2:
                        if (currentIndex == 2) {
                            setIndicatorPosition(offset + scrollWidth * 2);
                            Log.e("000", "2-->currentIndex == 2");
                        }
                        break;
                }
            }

            @Override
            public void onPageSelected(int position) {
                currentIndex = position;//已選中位置:012
                Log.e("000", "onPageSelected==currentIndex==" + currentIndex);
                switch (position) {
                    case 0:
                        tab1.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
                        tab2.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
                        tab3.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);

                        setTabsColor(tab1);
//                        setIndicatorPosition(offset);
                        break;

                    case 1:
                        tab2.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
                        tab1.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
                        tab3.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);

                        setTabsColor(tab2);
//                        setIndicatorPosition(offset + scrollWidth);
                        break;

                    case 2:
                        tab3.animate().scaleX(1.5f).scaleY(1.5f).setDuration(200);
                        tab2.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);
                        tab1.animate().scaleX(1.0f).scaleY(1.0f).setDuration(200);

                        setTabsColor(tab3);
//                        setIndicatorPosition(offset + scrollWidth * 2);
                        break;
                }

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void setIndicatorPosition(int offset) {
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(cursor.getLayoutParams());
        layoutParams.setMargins(offset, 0, 0, 0);
        cursor.setLayoutParams(layoutParams);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tab1:
                mVp.setCurrentItem(0);
                break;
            case R.id.tab2:
                mVp.setCurrentItem(1);
                break;
            case R.id.tab3:
                mVp.setCurrentItem(2);
                break;

        }
    }

    private void setTabsColor(TextView textView) {
        tab1.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));
        tab2.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));
        tab3.setTextColor(ContextCompat.getColor(this, R.color.defalut_color));

        textView.setTextColor(ContextCompat.getColor(this, R.color.select_color));
    }


}

ViewPagerForScrollView

解決viewpager(內含listview)隨scrollview一起滑動

/**
 * ScrollView巢狀viewpager
 */

public class ViewPagerForScrollView extends ViewPager {
    public ViewPagerForScrollView(Context context) {
        super(context);
    }

    public ViewPagerForScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int height = 0;
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
            int h = child.getMeasuredHeight();
            if (h > height)
                height = h;
        }

        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

MyListView

解決listview不顯示


public class MyListView extends ListView {

    public MyListView(Context context) {
        super(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    /**
     * 自適應
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);

    }
}

Fragment1

需設定 mLv.setFocusable(false);解決不置頂的問題

public class Fragment1 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment1_layout, container, false);
        ListView mLv = ((ListView) view.findViewById(R.id.lv));
        mLv.setDivider(new ColorDrawable(Color.parseColor("#ff0000")));
        mLv.setDividerHeight(5);

        mLv.setFocusable(false);
        return view;
    }
}

最後

這樣就實現了viewpager隨scrollview一起滾動 ,但是還有一個問題就是如果三個fragment頁面的listview高度不統一,那麼fragment將依靠最高的那一個為準,也就是說會有比較矮的fragment有空白。
比如:
這裡寫圖片描述