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.写分类导航栏的布局文件
<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 = position;
if (pos < leftInvisibleNum)//如果去往的页面是未可见
{
//mHorizontalScrollView向右滑动
mHorizontalScrollView.scrollBy(rec.getWidth() * -1, 0);
computeScrollParm();//计算TextView的数量
}
}
else //如果要去往的页面是在当前页面的右边
{
pos++;
if(7-pos //如果去往的页面是未可见,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;
}
至此,已经能实现文章开始说的功能了。
总结: