首页 > 系统 > Android > 正文

Android 滑动定位和吸附悬停效果实现代码

2019-10-21 21:42:36
字体:
来源:转载
供稿:网友

在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接:

Android tabLayout+recyclerView实现锚点定位

仔细看的话,这种滑动定位的功能,还可以整体滑动,再加上顶部tablayout 吸附悬停的效果。

实现效果:

Android,滑动定位,吸附悬停效果

布局

这里采用的是两个 tablayout。

一个用于占位,位于原始位置,scrollview内部,随scrollview滚动;另一个则是在滑动过程中,不断滑动,滑动到顶部时吸附在屏幕顶部,用户实际操作的也是这个tablayout。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical">  <com.tabscroll.CustomScrollView    android:id="@+id/scrollView"    android:layout_width="match_parent"    android:layout_height="match_parent">    <FrameLayout      android:layout_width="match_parent"      android:layout_height="match_parent">      <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="vertical">        <LinearLayout          android:layout_width="match_parent"          android:layout_height="200dp"          android:background="#ccc"          android:gravity="center">          <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="这里是顶部内容区域"            android:textSize="16sp" />        </LinearLayout>        <!--占位的tablayout-->        <android.support.design.widget.TabLayout          android:id="@+id/tablayout_holder"          android:layout_width="match_parent"          android:layout_height="50dp"          android:background="#ffffff"          app:tabIndicatorColor="@color/colorPrimary"          app:tabMode="scrollable"          app:tabSelectedTextColor="@color/colorPrimary" />        <LinearLayout          android:id="@+id/container"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:orientation="vertical"          android:padding="16dp" />      </LinearLayout>      <!--实际用户操作的tablayout-->      <android.support.design.widget.TabLayout        android:id="@+id/tablayout_real"        android:layout_width="match_parent"        android:layout_height="50dp"        android:background="#ffffff"        android:visibility="invisible"        app:tabIndicatorColor="@color/colorPrimary"        app:tabMode="scrollable"        app:tabSelectedTextColor="@color/colorPrimary" />    </FrameLayout>  </com.tabscroll.CustomScrollView></LinearLayout>

实现

滑动定位的功能可以参考之前的文章,这里主要是进行吸附悬停的效果。

数据初始化:

/** * 占位tablayout,用于滑动过程中去确定实际的tablayout的位置 */private TabLayout holderTabLayout;/** * 实际操作的tablayout, */private TabLayout realTabLayout;private CustomScrollView scrollView;private LinearLayout container;private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"};private List<AnchorView> anchorList = new ArrayList<>();//判读是否是scrollview主动引起的滑动,true-是,false-否,由tablayout引起的private boolean isScroll;//记录上一次位置,防止在同一内容块里滑动 重复定位到tablayoutprivate int lastPos = 0;//监听判断最后一个模块的高度,不满一屏时让最后一个模块撑满屏幕private ViewTreeObserver.OnGlobalLayoutListener listener;for (int i = 0; i < tabTxt.length; i++) {  AnchorView anchorView = new AnchorView(this);  anchorView.setAnchorTxt(tabTxt[i]);  anchorView.setContentTxt(tabTxt[i]);  anchorList.add(anchorView);  container.addView(anchorView);}for (int i = 0; i < tabTxt.length; i++) {  holderTabLayout.addTab(holderTabLayout.newTab().setText(tabTxt[i]));  realTabLayout.addTab(realTabLayout.newTab().setText(tabTxt[i]));}

一开始让实际的tablayout 移动到占位的tablayout 处,覆盖占位的tablayout。

listener = new ViewTreeObserver.OnGlobalLayoutListener() {  @Override  public void onGlobalLayout() {    //计算让最后一个view高度撑满屏幕    int screenH = getScreenHeight();    int statusBarH = getStatusBarHeight(AliHomeMoreActivity.this);    int tabH = holderTabLayout.getHeight();    int lastH = screenH - statusBarH - tabH - 16 * 3;    AnchorView anchorView = anchorList.get(anchorList.size() - 1);    if (anchorView.getHeight() < lastH) {      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);      params.height = lastH;      anchorView.setLayoutParams(params);    }    //一开始让实际的tablayout 移动到 占位的tablayout处,覆盖占位的tablayout    realTabLayout.setTranslationY(holderTabLayout.getTop());    realTabLayout.setVisibility(View.VISIBLE);    container.getViewTreeObserver().removeOnGlobalLayoutListener(listener);  }};container.getViewTreeObserver().addOnGlobalLayoutListener(listener);private int getScreenHeight() {  return getResources().getDisplayMetrics().heightPixels;}public int getStatusBarHeight(Context context) {  int result = 0;  int resourceId = context.getResources()      .getIdentifier("status_bar_height", "dimen", "android");  if (resourceId > 0) {    result = context.getResources().getDimensionPixelSize(resourceId);  }  return result;}

scrollview滑动

主要在滑动过程这不断监听滑动的距离,再移动实际的tablayout ,当在屏幕内时,让其一直覆盖在占位的tablayout 上,看上去是跟着scrollview 一起滑动的;当滑出屏幕时,实际的tablayout 不断移动 使其相对屏幕静止,看上去是吸附在屏幕顶部。

scrollView.setOnTouchListener(new View.OnTouchListener() {  @Override  public boolean onTouch(View v, MotionEvent event) {    if (event.getAction() == MotionEvent.ACTION_DOWN) {      isScroll = true;    }    return false;  }});//监听scrollview滑动scrollView.setCallbacks(new CustomScrollView.Callbacks() {  @Override  public void onScrollChanged(int x, int y, int oldx, int oldy) {    //根据滑动的距离y(不断变化的) 和 holderTabLayout距离父布局顶部的距离(这个距离是固定的)对比,    //当y < holderTabLayout.getTop()时,holderTabLayout 仍在屏幕内,realTabLayout不断移动holderTabLayout.getTop()距离,覆盖holderTabLayout    //当y > holderTabLayout.getTop()时,holderTabLayout 移出,realTabLayout不断移动y,相对的停留在顶部,看上去是静止的    int translation = Math.max(y, holderTabLayout.getTop());    realTabLayout.setTranslationY(translation);    if (isScroll) {      for (int i = tabTxt.length - 1; i >= 0; i--) {        //需要y减去顶部内容区域的高度(具体看项目的高度,这里demo写死的200dp)        if (y - 200 * 3 > anchorList.get(i).getTop() - 10) {          setScrollPos(i);          break;        }      }    }  }});private void setScrollPos(int newPos) {  if (lastPos != newPos) {    realTabLayout.setScrollPosition(newPos, 0, true);  }  lastPos = newPos;}

tablayout点击切换

由于实际操作的是realtablayout ,所以这里只需要一直监听该tablayout。

//实际的tablayout的点击切换realTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {  @Override  public void onTabSelected(TabLayout.Tab tab) {    isScroll = false;    int pos = tab.getPosition();    int top = anchorList.get(pos).getTop();    //同样这里滑动要加上顶部内容区域的高度(这里写死的高度)    scrollView.smoothScrollTo(0, top + 200 * 3);  }  @Override  public void onTabUnselected(TabLayout.Tab tab) {  }  @Override  public void onTabReselected(TabLayout.Tab tab) {  }});

至此,滑动定位+顶部吸附悬停 的效果结束了。做完之后,再看这个效果,其实和 支付宝-首页 更多 那个页面里的滑动效果一样。

代码与之前文章的在同一个git地址里。

详细代码见

github地址: https://github.com/taixiang/tabScroll

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表