Android滑动悬停

先上图

(好多效果文章都不带图,我觉得先放图也能给大家节省时间,合适了在往下看)

今天在开发的时候有这样的一种需求,百度好久,没有满意的,基本上代码扔一堆太复杂而且也没有整理,没心情看,最后放弃。

决定自己研究,尝试了两种思路:为了方便,给要固定的那一栏起个名字叫    A   吧

1.最初我想通过两个ScrollView,第一个Scroll里面放(内容,A和 第二个Scroll)。当第一个Scroll大小滑完之后,会留A和第二个Scroll占满全屏,继续滑动的时候当然只会滑动第二个Scroll,自然A就保持在顶部,这个最好想,应该可以实现,但是每个手机分辨率不一样,刻意去设置大小可能会不兼容。放弃这个思路。

重点在这

2.第二个是判断当A滑出屏外的时候,把A从Scroll拿出来,然后放到顶部。当判断A滑入屏幕里面在把A放入Scroll里面。上图就是第二种,看起来固定的很完美,我反正是看不出来有什么瑕疵

看布局代码,这个主要是理解,理解之后就能72变,布局代码

//最外层用相对布局,为了让放置A的容器固定在屏幕顶部,并且挡住ScrollView
<RelativeLayout>
    //蓝色是滑动控件和线性布局组合
    <ScrollView> 
      <LinearLayout >

            //这个是放A的容器
            <LinearLayout>
               //这是A
                <LinearLayout>
                    
                </LinearLayout>

            </LinearLayout>

      </LinearLayout>
    </ScrollView>

    //这是悬浮A的容器,想放哪都行,根据需要 放左 放右 放上 放下。
    <RelativeLayout>

    </RelativeLayout>
</RelativeLayout>

这个布局总的来讲就是需要给A准备两个盛放容器,一个滑动的,一个固定的

然后java代码很少,仅仅给ScrollView 设置滑动监听、然后里面进行简单  if  就可以了 

 下面代码里    linewai1   是滑动容器中放  A  的容器,re1是放  A  悬浮容器

public void listener(){
  scrol.setOnScrollChangeListener(new View.OnScrollChangeListener() {
    @Override
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        if(scrollY>=linewai1.getY()){
            removeOneself(A);
            re1.addView(A);
        }else if(linewai1.indexOfChild(A)<0){//这里判断A是否在A原来的容器里,没有的话就把A从悬浮容器移除
            removeOneself(A);
            linewai1.addView(A);//放置到滑动容器
        }
     }
  });

}

这里提一下,如何判断一个控件是否被滑出屏幕,这个也是问题,百度没找到答案,我是根据控件的相对坐标来进行判定的,这里利用ScrollView的滑动距离和放置A的容器的getY(  )来判断的,实验发现,当一个控件被滑出屏幕,那滑动距离一定大于该控件的相对Y坐标。当小于的时候该控件是应该显示出来的。

当A滑出屏幕,就从原容器移除,放到悬浮容器中,当A滑入屏幕,反向操作。

这里值得注意的是,从容器中移除A,不能简单的利用layout.removeview(View view)这个方法,会报错的,只能从父控件中移除子控件,但是布局和A并不是直接的父子关系,需要调入如下方法,这个方法是借鉴一位大佬的方法。

public static void removeOneself(View child){
    if (child != null){
        ViewGroup parent = (ViewGroup)child.getParent();
        if (parent != null && parent instanceof ViewGroup) {
            parent.removeView(child);
        }
    }
}

这个方法直接用就可以了

只要布局设置好,只要一个滑动监听就够了,是不是代码很少?前面提到的72变,理解了这个,是不是底部悬浮,左侧悬浮,右侧悬浮,乱七八糟的悬浮都OK了,😄😄😄😄😄😄

还有比这个简单的么,欢迎留言😛😛😛😛😛

小小的踩坑经验分享完毕,有帮助的话给我个提醒赞哦

附件完整样例

xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ScrollView
        android:id="@+id/scrol"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#B17AFF"
                android:text="填充1"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:background="#8BC8F8"
                android:text="填充1"/>
            <LinearLayout
                android:id="@+id/sliding_box"
                android:layout_width="match_parent"
                android:layout_height="80dp"
                android:orientation="vertical">

                <HorizontalScrollView
                    android:id="@+id/A"
                    android:layout_width="match_parent"
                    android:background="#ffffff"
                    android:scrollbars="none"
                    android:layout_height="80dp">
                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="80dp"
                        android:orientation="horizontal">
                        <Button
                            android:layout_width="200dp"
                            android:layout_height="70dp"
                            android:layout_gravity="center_vertical"
                            android:backgroundTint="#FFDE7A"
                            android:text="1"/>
                        <Button
                            android:layout_width="200dp"
                            android:layout_height="70dp"
                            android:layout_gravity="center_vertical"
                            android:backgroundTint="#51E8CA"
                            android:text="2"/>
                        <Button
                            android:layout_width="200dp"
                            android:layout_height="70dp"
                            android:layout_gravity="center_vertical"
                            android:backgroundTint="#F19D97"
                            android:text="3"/>

                    </LinearLayout>

                </HorizontalScrollView>



            </LinearLayout>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="500dp"
                android:background="#FFF06A"
                android:text="填充2"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="500dp"
                android:background="#77EF7C"
                android:text="填充2"/>

        </LinearLayout>

    </ScrollView>

    <RelativeLayout
        android:id="@+id/top_box"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:layout_alignParentTop="true">



    </RelativeLayout>


</RelativeLayout>

java:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;

public class MainActivity extends AppCompatActivity {
    private RelativeLayout top_box;
    private ScrollView scrol;
    private LinearLayout sliding_box;
    private HorizontalScrollView A;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        listener();

    }

    public void init(){
        top_box=findViewById(R.id.top_box);
        scrol=findViewById(R.id.scrol);
        sliding_box=findViewById(R.id.sliding_box);
        A=findViewById(R.id.A);




    }

    public void listener() {
        scrol.setOnScrollChangeListener(new View.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                if (scrollY >= sliding_box.getY()) {
                    removeOneself(A);
                    top_box.addView(A);
                } else if (sliding_box.indexOfChild(A) < 0) {//这里判断A是否在A原来的容器里,没有的话就把A从悬浮容器移除
                    removeOneself(A);
                    sliding_box.addView(A);//放置到滑动容器
                }
            }
        });
    }
    public static void removeOneself(View child){
        if (child != null){
            ViewGroup parent = (ViewGroup)child.getParent();
            if (parent != null && parent instanceof ViewGroup) {
                parent.removeView(child);
            }
        }
    }



}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值