1. 程式人生 > >HorizontalScrollView作為導航欄和HorizontalScrollView的滑動

HorizontalScrollView作為導航欄和HorizontalScrollView的滑動

HorizantalScrollView和ScrollView差不多,不過就是滑動的方向是水平方向上的,可以做APP的分類導航欄,就比如下圖:
這裡寫圖片描述

但是呢,導航欄不只是“推薦”、“體育”、“文藝”、“娛樂”這五個分類,在“娛樂”的右邊還有3噶分類,只是沒顯示出來出來而已。

下面分類的具體內容用的是ViewPager,翻頁的時候分類名稱下那條紅色的線條也會跟著移動到相應的分類名稱下,就像是這樣(這是翻頁的中間,還沒到第二頁的時候)
這裡寫圖片描述

這是翻到了第二頁時候的樣子
這裡寫圖片描述

當翻到“娛樂”分類右邊的“科技”分類的時候,“科技”這個分類也會顯示出來,當然,紅色的底線也是移動到它的下面。就像下圖
這裡寫圖片描述

接下來,就是實現的程式碼了:

1.重寫HorizontalScrollView裡的onOverScrolled,為了手動滑動這個HorizontalScrollView,能執行相應的操作。

package com.example.user.myvideo.Activity;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.HorizontalScrollView;
import android.widget.Scroller;

/**
 * Created by Administrator on 2016/7/13 0013.
 */
public class MyHorizontalScrollView extends HorizontalScrollView { Scroller scroller; public MyHorizontalScrollView(Context context) { super(context); scroller = new Scroller(context); } public MyHorizontalScrollView(Context context, AttributeSet attrs) { super
(context, attrs); scroller = new Scroller(context); } public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); scroller = new Scroller(context); } public MyHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); scroller = new Scroller(context); } /* 當手動滑動完成時呼叫回撥方法。 */ @Override protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); if(mOnOverScrolledListener != null) { mOnOverScrolledListener.onOverScrolled(scrollX, scrollY, clampedX, clampedY); } } /* 設定回撥介面 */ public void setOnOverScrolledListener(OnOverScrolledListener mOnOverScrolledListener) { this.mOnOverScrolledListener = mOnOverScrolledListener; } private OnOverScrolledListener mOnOverScrolledListener; /* 定義回撥介面 */ public interface OnOverScrolledListener { public abstract void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY); } }

2.寫分類導航欄的佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toplist"
    android:layout_width="match_parent"
    android:layout_height="35dp"
    android:background="@color/topbackground"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/visible_window"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">
        <com.example.user.myvideo.Activity.MyHorizontalScrollView
            android:id="@+id/id_list"
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:scrollbars="none">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="33dp"
                    android:orientation="horizontal">
                    <TextView
                        android:id="@+id/id_rec"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/recommend"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_spo"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/sport"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_edu"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/education"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_art"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/art"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_ent"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/entertain"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_sci"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/science"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_pla"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/living"
                        android:textColor="@color/black"/>
                    <TextView
                        android:id="@+id/id_mor"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:text="@string/more"
                        android:textColor="@color/black"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="2dp">
                    <View
                        android:id="@+id/id_tabline"
                        android:layout_width="55dp"
                        android:layout_height="match_parent"
                        android:background="@color/orange"/>
                </LinearLayout>
            </LinearLayout>
        </com.example.user.myvideo.Activity.MyHorizontalScrollView>

    </LinearLayout>


    <ImageView
        android:id="@+id/id_cm"
        android:layout_width="35dp"
        android:layout_height="match_parent"
        android:src="@drawable/manage"/>

</LinearLayout>

3.在MainActivity裡面初始化一些要用的View。

mHorizontalScrollView= (MyHorizontalScrollView) findViewById(R.id.id_list);
visibleWindow = (LinearLayout) findViewById(R.id.visible_window);
rec = (TextView) findViewById(R.id.id_rec);
mViewPager = (MyViewPager) findViewById(R.id.id_viewpager);
tabline = findViewById(R.id.id_tabline);

4.重寫MainActivity的onWindowFocusChanged方法。

/*
    * visibleNum 是可見的範圍內TextView的數量,rightInvisibleNum 是可見範圍右邊未可見的TextView的數量
    * leftInvisibleNum 是可見範圍左邊未可見的TextView的數量,此三變數為MainActivity的私有變數。
    * 這段程式碼不能放在onCreate方法裡面,因為rec還沒有圖形介面,不能獲取寬度。
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        int singleTextVieweWidth = rec.getWidth();
        leftInvisibleNum = 0;
        visibleNum = visibleWindow.getWidth()/singleTextVieweWidth;
        rightInvisibleNum = 8 -visibleNum;
    }

5.設定mHorizontalScrollView的回撥方法。

/*
        * 設定list的回撥方法,主要是計算左邊未可見TextView,右邊未可見TextView和可見TextView的數量
         */
        mHorizontalScrollView.setOnOverScrolledListener(new MyHorizontalScrollView.OnOverScrolledListener() {
            @Override
            public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
                Toast.makeText(MainActivity.this,"Scrolling completed!",Toast.LENGTH_LONG).show();
                int singleTextVieweWidth = rec.getWidth();
                leftInvisibleNum =0;
                if (scrollX !=0) {
                    //如果左邊未見的TextView沒有整數數量的話,就取整加1
                    leftInvisibleNum = scrollX / singleTextVieweWidth + (scrollX % singleTextVieweWidth == 0? 0:1);
                }
                visibleNum = (visibleWindow.getWidth()-scrollX%singleTextVieweWidth)/singleTextVieweWidth;rightInvisibleNum = 8 - leftInvisibleNum - visibleNum;
            }
        });

6.實現的mViewPager的OnPageChangeListener實現回撥。

//ViewPager進行頁面切換的時候的監聽器
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //postion是目前所在位置,為整數:0,1,2,3,5...,positionOffset是位置偏移量,
                // positionOffsetPixels是偏移的畫素。


                //設定紅色底線的位置,setX是相對於父控制元件的X位置。(position+positionOffset)*底線寬度就
                // 是底線應該在具體位置(相對於父控制元件的具體位置)
                tabline.setX((float) (position * tabline.getWidth() + positionOffset * tabline.getWidth()));
                //pos是靜止時的頁號,或者是要去往的頁號
                if(positionOffset == 0.0f)
                {
                    pos = position;
                }
                //當要翻頁時,進行判斷和滑動
                if (positionOffset != 0.0f)
                {
                    if (position <pos)//如果要去往的頁面是在當前頁面的左邊
                    {
                        pos = position;
                        if (pos < leftInvisibleNum)//如果去往的頁面是未可見
                        {
                            //mHorizontalScrollView向右滑動
                            mHorizontalScrollView.scrollBy(rec.getWidth() * -1, 0);
                            computeScrollParm();//計算TextView的數量
                        }

                    }
                    else  //如果要去往的頁面是在當前頁面的右邊
                    {
                        pos++;
                        if(7-pos <rightInvisibleNum)//如果去往的頁面是未可見,7為最後一個頁面的頁號
                        {
                            //mHorizontalScrollView向左滑動
                            mHorizontalScrollView.scrollBy(rec.getWidth(), 0);
                            computeScrollParm();
                        }
                    }
                }
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

7.computeScrollParm方法

private void computeScrollParm()
    {
        int scrollX = mHorizontalScrollView.getScrollX();
        int singleTextVieweWidth = rec.getWidth();
        leftInvisibleNum =0;
        if (scrollX() !=0)
        {
            leftInvisibleNum = scrollX / singleTextVieweWidth + (scrollX%singleTextVieweWidth == 0?0:1);
        }
        visibleNum = (visibleWindow.getWidth()-scrollX%singleTextVieweWidth)/singleTextVieweWidth;
        rightInvisibleNum = 8 - leftInvisibleNum - visibleNum;
    }

至此,已經能實現文章開始說的功能了。

總結:

  1. HorizontalScrollView的onOverScrolled方法會在手動滑動完成的時候會呼叫。
  2. ViewPager頁面切換監聽器 OnPageChangeListener裡的onPageScrolled回撥方法可以通過其引數確定具體位置,可以通過頁面切換時position變小還是不變來確定是向左還是向右翻頁。
  3. View.setX方法是設定View在父控制元件的相對X位置。
  4. View.getScrollX方法是獲取View的mScrollX的值,也就是相對於父控制元件x方向上Scrolled的值。
  5. 可以定義介面來實現一些回撥方法。