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. 可以定义接口来实现一些回调方法。

猜你喜欢

转载自blog.csdn.net/u014686721/article/details/51943143