Android滑动ScrollView时使导航栏停留的效果(仿ios的tableview分区)

来源:互联网 发布:志鸿优化系列丛书 编辑:程序博客网 时间:2024/06/06 19:37


        首先,我们来看下效果图,如下:


 


       让我们来分析一下这个图,这是一个scrollview,有4个条目,当我们向上滑动的时候,如果条目2滑到顶端,会把

条目1顶上去,然后条目2停留,等待条目3上来,之后条目3会把条目2顶上去,然后停留,后面同理。

那么,这个动态的怎么来实现呢?停留的导航栏是什么呢?


        其实,导航栏是一个浮在scrollView上面的一个textView。当条目2滚动到条目1下面的时候,让textview动态的随

着scrollview的滚动而滚动直至条目1滚出屏幕。当条目2滚动到条目1的位置的时候让textView显示在条目1 的位置,

当scrollview继续滚动的时候textview不动,给人一种条目2停留的感觉。以下同理。


        好,大概的原理我们已经大致的清楚了,那就开始来看一下布局吧!


<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><RelativeLayout 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">    <com.example.peiwc.iostableview.MyScrollView        android:id="@+id/scv"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <TextView                android:id="@+id/title0"                android:layout_width="match_parent"                android:layout_height="55dp"                android:background="#ffF19EDB"                android:gravity="center"                android:textStyle="bold"                android:text="条目1" />            <TextView                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text1"                android:textSize="26sp" />            <TextView                android:id="@+id/title1"                android:layout_width="match_parent"                android:layout_height="55dp"                android:background="@color/colorRed"                android:gravity="center"                android:text="条目2"                android:textStyle="bold"                android:textSize="22sp"                android:textColor="@android:color/white"/>            <TextView                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text2"                android:textSize="26sp" />            <TextView                android:id="@+id/img"                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text3"                android:textSize="26sp" />            <TextView                android:id="@+id/title2"                android:layout_width="match_parent"                android:layout_height="55dp"                android:background="@color/colorYel"                android:gravity="center"                android:text="条目3"                android:textSize="22sp"                android:textColor="@android:color/white"                android:textStyle="bold"/>            <TextView                android:id="@+id/iv1"                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text4"                android:textSize="26sp" />            <TextView                android:id="@+id/title3"                android:layout_width="match_parent"                android:layout_height="55dp"                android:background="@color/colorBlue"                android:gravity="center"                android:text="条目4"                android:textSize="22sp"                android:textColor="@android:color/white"                android:textStyle="bold"/>            <TextView                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text5"                android:textSize="26sp" />            <TextView                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text6"                android:textSize="26sp" />            <TextView                android:layout_width="match_parent"                android:layout_height="300dp"                android:adjustViewBounds="true"                android:gravity="center"                android:scaleType="fitCenter"                android:text="text7"                android:textSize="26sp" />        </LinearLayout>    </com.example.peiwc.iostableview.MyScrollView>    <TextView        android:id="@+id/title"        android:layout_width="match_parent"        android:layout_height="55dp"        android:background="@color/colorZi"        android:gravity="center"        android:textSize="22sp"        android:textColor="@android:color/white"        android:textStyle="bold"        android:text="条目1" /></RelativeLayout></span></span>

       这个布局整体是个Relativelayout,里面在scrollview上面有一个textview title,我们给4个条目都设置了id,分别是title0,title1,title2,title3.可以看到scrollview被重写了


       为什么要重写scrollview呢?


       因为我们要对scrollview进行监听,获得scrollview滑动的距离,从而控制title的位移。可惜sdk并没哟响应的方法,但是scrollview中倒是提供了一个方法


<pre name="code" class="java"><span style="font-size:18px;">  @Override    protected void onScrollChanged(int x, int y, int oldx, int oldy) {        super.onScrollChanged(x, y, oldx, oldy);        if (scrollViewListener != null) {            scrollViewListener.onScrollChanged( x, y, oldx, oldy);        }    }</span>


显然这个方法是不能被外界调用的,因此我们要把它暴露出去,方便使用。

         下面帖上程序代码我们来具体看下ScrollView:

<pre name="code" class="java"><span style="font-size:18px;">public class MyScrollView extends ScrollView {    private ScrollViewListener scrollViewListener = null;    public MyScrollView(Context context) {        super(context);    }    public MyScrollView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public interface ScrollViewListener {        void onScrollChanged( int x, int y, int oldx, int oldy);    }    public void setScrollViewListener(ScrollViewListener scrollViewListener) {        this.scrollViewListener = scrollViewListener;    }//    onScrollChanged里面有4个参数,l代表滑动后当前ScrollView可视界面的左上角在整个ScrollView的X轴中的位置,oldi也就是滑动前的X轴位置了。//    同理,t也是当前可视界面的左上角在整个ScrollView的Y轴上的位置,oldt也就是移动前的Y轴位置了。    @Override    protected void onScrollChanged(int x, int y, int oldx, int oldy) {        super.onScrollChanged(x, y, oldx, oldy);        if (scrollViewListener != null) {            scrollViewListener.onScrollChanged( x, y, oldx, oldy);        }    }}</span>


       接下来,就是我们华丽丽的Activity闪亮登场啦!先把整篇帖上去,然后我再仔细讲。

<pre name="code" class="java"><span style="font-size:18px;">public class MainActivity extends Activity implements MyScrollView.ScrollViewListener{    private TextView title0,title1,title2,title3,title;    private long topDistance0,topDistance1,topDistance2,topDistance3,height;    private MyScrollView scrollView;    private int distance;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        title0=(TextView)findViewById(R.id.title0);        title1=(TextView)findViewById(R.id.title1);        title2=(TextView)findViewById(R.id.title2);        title3=(TextView)findViewById(R.id.title3);        title=(TextView)findViewById(R.id.title);        scrollView=(MyScrollView)findViewById(R.id.scv);        scrollView.setScrollViewListener(this);    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        if(hasFocus){            topDistance0 = title0.getTop();            topDistance1 = title1.getTop();            topDistance2 = title2.getTop();            topDistance3 = title3.getTop();//按钮左上角相对于父view(LinerLayout)的y坐标            height = title.getMeasuredHeight();            Log.i("","=topDistance0="+topDistance0);            Log.i("","=topDistance1="+topDistance1);            Log.i("","=topDistance2="+topDistance2);            Log.i("","=topDistance3="+topDistance3);            Log.i("","=topDistance3="+topDistance3);            Log.i("","=height="+height);        }    }    @Override    public void onScrollChanged(int x, int y, int oldx, int oldy) {        Log.i("","=topDistance=distance="+"x="+x+";y="+y+";oldx="+oldx+";oldy"+oldy);        distance=y;        distancePlace(topDistance0,topDistance1);        distancePlaceLayout(topDistance1,topDistance0);        distancePlace(topDistance1,topDistance2);        distancePlaceLayout(topDistance2,topDistance1);        distancePlace(topDistance2,topDistance3);        distancePlaceLayout(topDistance3,topDistance2);        if (distance > topDistance3) {            title.layout(0,0,title.getRight(),(int)height);            showText(topDistance3);        }    }    private void distancePlaceLayout(long topDistance1,long topDistance0){        if(distance>topDistance1-height && distance<topDistance1 ){            title.layout(0,(int)(topDistance1-distance-height),title.getRight(),(int)(topDistance1-distance));            showText(topDistance0);        }    }    private void distancePlace(long topDistance0,long topDistance1){        if(distance >= topDistance0&& distance<topDistance1-height){            title.layout(0,0,title.getRight(),(int)height);            showText(topDistance0);        }    }    private void showText(long topDistance){        if(topDistance==topDistance0){            title.setText("条目1");            title.setBackground(getResources().getDrawable(R.color.colorZi));        }        if(topDistance==topDistance1){            title.setText("条目2");            title.setBackground(getResources().getDrawable(R.color.colorRed));        }        if(topDistance==topDistance2){            title.setText("条目3");            title.setBackground(getResources().getDrawable(R.color.colorYel));        }        if(topDistance==topDistance3){            title.setText("条目4");            title.setBackground(getResources().getDrawable(R.color.colorBlue));        }    }}</span>


        在onWindowFocusChanged(boolean hasFocus)中,获取了4个条目的getTop值,即条目到scrollview顶端的距离。注意:getTop是控件左上角相对于父布局的y坐标。这个布局中所有条目的父布局都是scrollview,所以我们这里可以直接使用。我们看下打印的结果:

看下onScrollChange方法:

          当条目2到达条目1低端的时候,滑动的距离就应该是topDistance1-height,即title1.getTop-height,height是条目的高度。那么当条目2还没有到达条目1 低端的时候,如图,我们做了如下的判断:

<pre name="code" class="java"><span style="font-size:18px;">if(distance >= topDistance0 && distance<topDistance1-height){            title.layout(0,0,title.getRight(),(int)height);            showText(topDistance0);        }</span>


          当条目2到达条目1低端和条目1顶端之间的位置,即条目2往上推动条目1的时候

        滑动的距离就应该是topDistance1-height和即topDistance1之间,我们做了如下的判断:

<pre name="code" class="java"><span style="font-size:18px;">if(distance>topDistance1-height && distance<topDistance1 ){            title.layout(0,(int)(topDistance1-distance-height),title.getRight(),(int)(topDistance1-distance));            showText(topDistance0);        }</span>


       此时title是动态的,我们根据滑动的距离实时给title定个位。

        剩下的条目依次类推。

        把这两个判断做下封装,传入不同的距离值就可以啦!

        OK,demo完成!


源码:http://download.csdn.net/detail/aa_chao/9635014

1 0
原创粉丝点击