好久没写博客,没装逼了,今天没事干,就扩充一下博客内容吧!请先看图,动态的哦:
看完图以后,相信大家也差不多知道是什么意思了,我就不废话了,直接说实现方式了!
其实他的实现思路很简单,说的悬浮,其实并非是悬浮,而是利用隐藏和显示来实现这种视差效果,细心的人还会发现,里面有一个小小的动画效果在里面,就是超过那个临界点后,悬浮框会以一种反弹的方式,反弹回来,当然了,动画是不需要我们去做的,因为这是scrollview为我们已经封装好了的!接着说我们的思路,首先看我们没有悬浮框的时候,我们的条目所在位置,它是存在于顶部imageview控件下面的,那么我们只要在视图向上滑动的时候,判断是否已经滑到imageview控件的底部就可以了,拿到这个契机后,我们只需要让我们之前已经最备好了的一模一样的悬浮框条目显示出来就可以了,至于隐藏,反正推,也是一样的道理,这里就不过多的解释了!
关于返回顶部的小图标的显示/隐藏,在这里也解释一下,其实实现起来也很简单。首先设定他只有在向上滑动,直到listview中的第十个条目不可见时,并且是在手势向下的时候才会显示,前者很容易就可以做到,只需要调用适配器中的getview方法得到一个view对象,再将其装入measure测量一下也就ok了。难就难在手势的判断上,大多数的人,在这里他都会误以为这样的手势监听是写在MyScrollView中的onTuchEvent或者是onInterceptTuchEvent里面的,包括我一开始也是这样的想法,其实不然,我们都被懵住了,因为在Scrollview的滚动监听onScrollChanged()方法中,它已经为我们封装好了的,里面分别是四个参数,这里不解释,表示心疼!想要了解的可以查看这个博客:点击打开链接
根据其中的第二和第四的参数,我们就可以很容易来实现这一判断。下面看代码吧:
package bw.com.xingnengyouhua; import android.os.Build; import android.os.Bundle; import android.support.annotation.RequiresApi; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class Main2Activity extends AppCompatActivity { private MyListview lv; private ImageView img; private MyScollView scrollView; public ImageView tu; private Toolbar toolbar; private LinearLayout xuanfu; public interface JieKou { void chuan(int i); } JieKou jieKou; public void setJieKou(JieKou jieKou) { this.jieKou = jieKou; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); initView(); setArr(); //解决scollview默认显示在最底部的问题,让顶部图片获取焦点或使listview失去焦点 img.setFocusable(true); img.setFocusableInTouchMode(true); //通过视图树获取顶部imagview和toolbar的高度 img.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public void onGlobalLayout() { int height = img.getHeight();//获取顶部图片高度 int height1 = toolbar.getHeight();//获取toolbar的高度 height=height+height1; Log.i("jiba", "getViewTreeObserver====" + height); // 因为OnGlobalLayoutListener可能会被多次触发,所以在第一次测量完以后就需要将它移除,这样不仅起到了测量的作用,还能在内存上起到节省的好处 img.getViewTreeObserver().removeOnGlobalLayoutListener(this); jieKou.chuan(height); //将两种控件高度和回传到ui线程中 } }); //设置scrollview的临界值 setListView(); //点击事件返回顶部 分为两种有动画/没有动画 tu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(Main2Activity.this, "返回顶部", Toast.LENGTH_SHORT).show(); scrollView.smoothScrollTo(0, 0); } }); } public void setListView() { setJieKou(new JieKou() { @Override public void chuan(int i) { final int IMGGAO=i; MyAdapter myAdapter = new MyAdapter(Main2Activity.this, list); lv.setAdapter(myAdapter); //循环计算listview条目的前十条高度,并将其加入顶部控件高度,用来判断“返回顶部”的图标显示/隐藏 for (int j = 0; j < list.size(); j++) { if (j <= 9) { View view = myAdapter.getView(j, null, lv); view.measure(0, 0); int measuredHeight = view.getMeasuredHeight(); i = i + measuredHeight; } } //调用scrollview的回传接口,判断toolbar的悬浮与图标的显示/隐藏 final int finalI = i; scrollView.setScollViewListener(new MyScollView.ScollViewListener() { @Override public void scollListener(MyScollView myScollView, int l, final int t, int oldl, int oldt) { //判断scrollview向上滑动时,视图所超出屏幕的部分,是否大于等于顶部imageview的高度 if (IMGGAO <= t) { xuanfu.setVisibility(View.VISIBLE);//将toolbar显示 }else{ xuanfu.setVisibility(View.GONE);//将toolbar隐藏,并不占位,可以起到性能优化的作用 } //判断变化后的不可见高度(t)是否大于顶部imageview+toolbar+10个条目控件的高度总和 if (t > finalI) { //大于的总和高度的话,还要判断手势是向下还是向上滑动, if(t//变化后的高度小于变化前的高度,呈现递减的模式,表示手势是向下的 tu.setVisibility(View.VISIBLE);//向下,要显示 }else{ tu.setVisibility(View.GONE); //向上,要隐藏 } } else { tu.setVisibility(View.GONE); //没超过高度总和,要隐藏 } } }); } }); } List list = new ArrayList<>(); //创建数据源 public void setArr() { for (int i = 0; i < 50; i++) { list.add("这是数据" + i); } } //id初始化 private void initView() { lv = (MyListview) findViewById(R.id.lv); img = (ImageView) findViewById(R.id.img); scrollView = (MyScollView) findViewById(R.id.scrollView); tu = (ImageView) findViewById(R.id.tu); toolbar = (Toolbar) findViewById(R.id.toolbar); xuanfu= (LinearLayout) findViewById(R.id.xuan); } }
//自定义ScrollView
package bw.com.xingnengyouhua; import android.content.Context; import android.util.AttributeSet; import android.widget.ScrollView; /** * Created by mypc on 2018/3/7. */ public class MyScollView extends ScrollView { private float y; public MyScollView(Context context, AttributeSet attrs) { super(context, attrs); } public interface ScollViewListener{ void scollListener(MyScollView myScollView,int l, int t, int oldl, int oldt); } ScollViewListener scollViewListener; public void setScollViewListener(ScollViewListener scollViewListener) { this.scollViewListener = scollViewListener; } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); scollViewListener.scollListener(this,l, t, oldl, oldt); } }
//自定义ListView
package bw.com.xingnengyouhua; import android.content.Context; import android.util.AttributeSet; import android.widget.ListView; /** * Created by mypc on 2018/3/7. */ public class MyListview extends ListView { public MyListview(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
//ToolBar布局
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFF" > <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginLeft="-15dp" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:background="@drawable/shibaitu" android:layout_centerVertical="true" android:layout_marginLeft="15dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="小呆逼" android:textSize="20dp" android:textColor="#F00" /> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:background="@drawable/shibaitu" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="15dp"/> RelativeLayout> android.support.v7.widget.Toolbar> LinearLayout>
//主布局
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="bw.com.xingnengyouhua.Main2Activity"> <bw.com.xingnengyouhua.MyScollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="200dp" android:background="@drawable/datu"/> <include layout="@layout/toolbar"/> <bw.com.xingnengyouhua.MyListview android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv" >bw.com.xingnengyouhua.MyListview> LinearLayout> bw.com.xingnengyouhua.MyScollView> <ImageView android:id="@+id/tu" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:layout_marginBottom="100dp" android:background="@drawable/shibaitu" android:visibility="gone" /> <include layout="@layout/toolbar" android:visibility="gone" android:id="@+id/xuan" /> RelativeLayout>