简单的实现ScrollView 其中的子view滑动悬浮

简单的实现ScrollView 其中的子view滑动悬浮

先看看效果:

布局文件


<com.example.stickview.MyScrollView 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"
    tools:context="com.example.stickview.MainActivity"
    android:id="@+id/scroll_view">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:textSize="30sp"
            android:background="#dd33aa"
            android:gravity="center"
            android:text="top"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="2000dp"
            android:layout_marginTop="250dp"
            android:background="@drawable/bg_shade">


        LinearLayout>
        
        <LinearLayout
            android:id="@+id/stick_view_space"
            android:layout_width="match_parent"
            android:layout_height="50dip"
            android:layout_marginTop="200dp"
            android:orientation="vertical">

        LinearLayout>

        
        <LinearLayout
            android:id="@+id/stick_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#cc1133">

            <TextView
                android:layout_width="fill_parent"
                android:layout_height="50dip"
                android:background="#00ff33"
                android:gravity="center"
                android:text="这  是   滚  动    的     等  一  下  固  定  在 上  面的视图" />

        LinearLayout>

    FrameLayout>

com.example.stickview.MyScrollView>

这里需要注意的是将需要置顶悬浮的View放在FrameLayout的最上层,不然可能会被其他的View挡住

package com.example.stickview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity implements ScrollListener{

    LinearLayout viewSpace;
    LinearLayout stickView;
    MyScrollView myScrollView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myScrollView = (MyScrollView) findViewById(R.id.scroll_view);
        myScrollView.registerListener(this);
        viewSpace = (LinearLayout) findViewById(R.id.stick_view_space);
        stickView = (LinearLayout) findViewById(R.id.stick_view);

        stickView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            //当布局文件加载完成时,会调用该方法
            @Override
            public void onGlobalLayout() {
               //初始化stickView的位置
                onScroll(0,0);
            }
        });
    }

    @Override
    public void onScroll(int top, int left) {
        /**
         * 根据scrollView的滑动距离,来动态移动stickView
         * setTranslationY(x) 当x为正数的时候stickView是向下移动的
         * 开始时 top< viewSpace.getTop() 所以stickView 的位置一直与viewSpace位置重合,随着ScrollView一起滑动
         * 当用户手动向上滑动MyScrollView的时候,stickView(或viewSpace)处于顶部的时候,此时top > viewSpace.getTop()
         * stickView就会相对scrollView向下运动,又因为scrollView是向下运动的,所以相对手机屏幕就是静止的啦,看起来就是悬浮在顶部
         */
        stickView.setTranslationY(Math.max(top, viewSpace.getTop()));
    }
}

最难理解的是这一句,也是现实这个功能最重要的一句代码
stickView.setTranslationY(Math.max(top, viewSpace.getTop()));
代码里面已经注释,不懂的可以看看
下面是一个实现滚动回调的ScrollView,代码简单

package com.example.stickview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ScrollView;

/**
 * User  : guanhuan
 * Date  : 2016/8/3
 * 将onScrollChanged暴露给外面调用
 */
public class MyScrollView extends ScrollView{

    private ScrollListener scrollListener;

    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);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        Log.e("Tag", "l = " + l + ", t = " + t + ", oldl =" + oldl + ",oldt =" + oldt);
        if (scrollListener != null) {
            scrollListener.onScroll(t, l);
        }
    }

    public void registerListener(ScrollListener scrollListener){
        this.scrollListener = scrollListener;
    }
}

实现这样的功能还有其他的实现,比如使用两个同样的view,一个放在顶部的位置,一个嵌套在ScrollView的里面,通过计算ScrollView的滑动距离,来隐藏或者显示其中的某一View,但是感觉这个实现有点麻烦。还是觉得我的这种实现更加简单易用。

你可能感兴趣的:(简单的实现ScrollView 其中的子view滑动悬浮)