美文网首页Android进阶之旅
Android 简单实现控件滑动固定效果

Android 简单实现控件滑动固定效果

作者: 饮水思源为名 | 来源:发表于2018-08-23 17:09 被阅读714次

    效果图:

    控件滑动固定

    实现思路:

      首先我们需要实时的获取滑动的Y值scrollDistanceY(可以理解为滑动了的距离),可以通过ScrollView的getScrollY();方法来获取。我们继承ScrollView重写Touch方法,随触摸事件反馈scrollDistanceY。需要特殊处理手指离开后屏幕还在滑动导致 scrollDistanceY改变的情况。
      在xml布局中,绿色的固定布局View我们需要写两个,一个与头部布局重合,位于APP顶部,另一个与列表中。在Activity我们获取内部固定布局距离顶部的高度,与我们实时获取的scrollDistanceY做比较,控制外部固定布局是否显示,达到效果图的效果。

    代码实现:

    1. 重写ScrollView,实时反馈scrollDistanceY
    package com.wusy.adv;
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.widget.ScrollView;
    
    
    /**
     * Created by XIAO RONG on 2018/8/23.
     * 这是一个能够实时向主View提供滑动距离Y值的ScrollView(滑动的高度)
     * 能够运用此ScrollView实现在内部View固定顶部布局的需求
     */
    
    public class FixedHeadScrollView extends ScrollView{
        public FixedHeadScrollViewListener listener;
        private int scrollDistanceY;
        private Handler handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case 1:
                        int newY=getScrollY();//在手指离开屏幕的短暂时间间隔后再次获取Y值
                        if(newY!=scrollDistanceY){//如果不相等,说明手指离开后,屏幕仍然在滑动,继续更新scrollDistanceY的值
                            scrollDistanceY=newY;
                            listener.sendDistanceY(scrollDistanceY);
                            handler.sendEmptyMessageDelayed(1,5);
                        }
                        break;
                }
            }
        };
        public FixedHeadScrollView(Context context) {
            this(context,null);
        }
    
        public FixedHeadScrollView(Context context, AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public FixedHeadScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if(ev.getAction()==MotionEvent.ACTION_UP){
                handler.sendEmptyMessageDelayed(1,30);
            }
            scrollDistanceY=getScrollY();
            listener.sendDistanceY(scrollDistanceY);
            return super.onTouchEvent(ev);
    
        }
    
        public interface  FixedHeadScrollViewListener{
            void sendDistanceY(int distance);
        }
    
        public void setFixedHeadScrollViewListener(FixedHeadScrollViewListener listener) {
            this.listener = listener;
        }
    }
    
    1. xml代码,固定布局要写两个,控制一个的显隐。
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/layout_total">
    
        <com.wusy.adv.FixedHeadScrollView
            android:id="@+id/scrollview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/layout_head"
                    android:layout_width="match_parent"
                    android:layout_height="200dp"
                    android:background="#e21919"
                    android:gravity="center"
                    android:text="头部布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:id="@+id/layout_fixed_inside"
                    android:layout_width="match_parent"
                    android:layout_height="50dp"
                    android:background="#10e91b"
                    android:gravity="center"
                    android:text="固定布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#19ace2"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#d408bc"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#f7eb00"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#192de2"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#19ace2"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#d408bc"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#f7eb00"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
    
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:background="#192de2"
                    android:gravity="center"
                    android:text="列表布局"
                    android:textColor="#ffffff"
                    android:textSize="17dp" />
            </LinearLayout>
    
        </com.wusy.adv.FixedHeadScrollView>
    
        <TextView
            android:id="@+id/layout_fixed_outside"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#10e91b"
            android:gravity="center"
            android:visibility="gone"
            android:text="固定布局"
            android:textColor="#ffffff"
            android:textSize="17dp" />
    </RelativeLayout>
    
    1. Activity中,实现FixedHeadScrollView提供的接口。获取内层固定布局距离固定位置的高度,与scrollDistanceY比较,当内层固定布局达到固定位置,则显示外层固定布局,反之隐藏。
    package com.wusy.adv;
    
    import android.util.Log;
    import android.view.View;
    import android.widget.TextView;
    
    import com.wusy.wusylibrary.base.BaseActivity;
    
    /**
     * Created by XIAO RONG on 2018/8/23.
     */
    
    public class HomeActivity extends BaseActivity implements FixedHeadScrollView.FixedHeadScrollViewListener{
        private TextView layout_inside,layout_outside;
        private int topDistance;
        private FixedHeadScrollView scrollView;
    
        @Override
        public int getContentViewId() {
            return R.layout.activity_home;
        }
    
        @Override
        public void findView() {
            layout_inside=findViewById(R.id.layout_fixed_inside);
            layout_outside=findViewById(R.id.layout_fixed_outside);
            scrollView=findViewById(R.id.scrollview);
        }
    
        @Override
        public void init() {
            scrollView.setFixedHeadScrollViewListener(this);
        }
    
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            if(hasFocus){
                topDistance=layout_inside.getTop();
                Log.i("msg","topDistance="+topDistance);
            }
        }
    
        @Override
        public void sendDistanceY(int distance) {
            Log.i("msg","看这里——"+distance);
            if(distance>=topDistance){
                layout_outside.setVisibility(View.VISIBLE);
            }else{
                layout_outside.setVisibility(View.GONE);
            }
        }
    }
    

    注意:

    1. 在获取内部固定布局距离顶部的距离的时候,不要在onCreate()中去执行,由于界面还没有完全绘制完成,获取到的距离值永远为0。建议在onWindowFocusChanged()中去获取。
    2. xml中,外部固定布局一定要放在scrollView外面。
    3. 记得处理手指离开屏幕后,界面仍然在滑动,导致外层固定布局的显示隐藏控制有误。

    我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=32rm642dvbr7

    相关文章

      网友评论

      • yemoumou:白日依山尽-简书朋友你好,我是币圈一老友,我的写作方向是区块链和数字货币,初到简书,望多多关照。互粉互赞,已赞,期待您的回赞哦。-撒
      • 有点健忘:为啥不用coordinatelayout,都出来这么多年了。
        饮水思源为名:@有点健忘 额,这方面之前看得比较少。我在做了这个demo就发现了desion包里这些东西。打开新世界大门

      本文标题:Android 简单实现控件滑动固定效果

      本文链接:https://www.haomeiwen.com/subject/mlkmiftx.html