凌雪
2018-11-29
来源 :网络
阅读 1283
评论 0
摘要:本文将带你了解Android应用开发之Android 仿支付宝城市服务栏目tab选择滑动子View效果,希望本文对大家学Android有所帮助。
本文将带你了解Android应用开发之Android 仿支付宝城市服务栏目tab选择滑动子View效果,希望本文对大家学Android有所帮助。
一. 图示
支付宝效果
实现的效果
二. 思路讲解
TabLayout+ScrollView实现即可。每一个tab对应scrollview中包裹的一层布局,以上有4个tab,也就需要inflate 4个布局文件,用来表示每一层的样式内容。
1.页面加载完毕后,记住每一层父布局在Screen中所要滑动至顶部的距离Distance;
2.操作:
a. 当点击tab时:滑动scrollview该层的距离Distance;
b. 当滑动scrollview至对应的层时: 选定对应的tab。
三. 代码
1. 布局代码
<!--?xml version="1.0" encoding="utf-8"?--><linearlayout android:id="@+id/activity_main" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" tools:context="com.ganshenml.tabscrollviewdemo.MainActivity" xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools"> <framelayout android:layout_height="wrap_content" android:layout_width="match_parent"> </android.support.design.widget.tablayout> <framelayout android:id="@+id/wrapperFl" android:layout_height="match_parent" android:layout_width="match_parent"></framelayout> </framelayout> <com.ganshenml.tabscrollviewdemo.observablescrollview android:id="@+id/scrollView" android:layout_height="wrap_content" android:layout_width="match_parent"> <linearlayout android:id="@+id/containerLl" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical"> </linearlayout> </com.ganshenml.tabscrollviewdemo.observablescrollview></linearlayout>
布局代码很简单,可能会有的疑问点有:
a. wrapperFl是用来干啥的?
b. ObservableScrollView又是个什么东西?
(后面说明)
2. 逻辑代码
public class MainActivity extends AppCompatActivity implements ObservableScrollView.ScrollViewListener { private static final String TAG = "MainActivity"; private FrameLayout wrapperFl; private TabLayout tabLayout; private ObservableScrollView scrollView; private LinearLayout containerLl; private boolean firstAlreadyInflated = true; private ViewGroup firstFloorVg; private ViewGroup secondFloorVg; private ViewGroup thirdFloorVg; private ViewGroup fourthFloorVg; private int secondFloorVgPositionDistance;//第二层滑动至顶部的距离 private int thirdFloorVgPositionDistance; private int fourthFloorVgPositionDistance; private int currentPosition = 0; private boolean tabInterceptTouchEventTag = true;//标志位,用来区分是点击了tab还是手动滑动scrollview @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initListeners(); } private void initViews() { wrapperFl = (FrameLayout) findViewById(R.id.wrapperFl); tabLayout = (TabLayout) findViewById(R.id.tabLayout); scrollView = (ObservableScrollView) findViewById(R.id.scrollView); containerLl = (LinearLayout) findViewById(R.id.containerLl); for (int i = 0; i < 4; i++) { tabLayout.addTab(tabLayout.newTab().setText("tab" + (i + 1))); } firstFloorVg = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.item_floor_first, null); secondFloorVg = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.item_floor_second, null); thirdFloorVg = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.item_floor_third, null); fourthFloorVg = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.item_floor_fourth, null); containerLl.addView(firstFloorVg); containerLl.addView(secondFloorVg); containerLl.addView(thirdFloorVg); containerLl.addView(fourthFloorVg); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (firstAlreadyInflated) {//获取各层离screen顶部的位置以及计算滑动值相应顶部所需要的距离 firstAlreadyInflated = false; int[] firstFloorVgPosition = new int[2]; int[] secondFloorVgPosition = new int[2]; int[] thirdFloorVgPosition = new int[2]; int[] fourthFloorVgPosition = new int[2]; firstFloorVg.getLocationOnScreen(firstFloorVgPosition); secondFloorVg.getLocationOnScreen(secondFloorVgPosition); thirdFloorVg.getLocationOnScreen(thirdFloorVgPosition); fourthFloorVg.getLocationOnScreen(fourthFloorVgPosition); int firstFloorVgPositionAnchor = firstFloorVgPosition[1]; int secondFloorVgPositionAnchor = secondFloorVgPosition[1]; int thirdFloorVgPositionAnchor = thirdFloorVgPosition[1]; int fourthFloorVgPositionAnchor = fourthFloorVgPosition[1]; Log.d(TAG, "第一层距离屏幕的距离是:" + firstFloorVgPosition[1]); Log.d(TAG, "第二层距离屏幕的距离是:" + secondFloorVgPosition[1]); Log.d(TAG, "第三层距离屏幕的距离是:" + thirdFloorVgPosition[1]); Log.d(TAG, "第四层距离屏幕的距离是:" + fourthFloorVgPosition[1]); secondFloorVgPositionDistance = secondFloorVgPositionAnchor - firstFloorVgPositionAnchor; thirdFloorVgPositionDistance = thirdFloorVgPositionAnchor - firstFloorVgPositionAnchor; fourthFloorVgPositionDistance = fourthFloorVgPositionAnchor - firstFloorVgPositionAnchor; } } private void initListeners() { wrapperFl.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.d(TAG,"wrapperFl onTouch"); tabInterceptTouchEventTag = true;//让tab来处理滑动 return false; } }); tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { currentPosition = tab.getPosition(); if(!tabInterceptTouchEventTag){//手动滑动页面时则不再次处理滑动 return; } scrollView.computeScroll(); switch (currentPosition) { case 0: scrollView.smoothScrollTo(0, 0); break; case 1: scrollView.smoothScrollTo(0, secondFloorVgPositionDistance); break; case 2: scrollView.smoothScrollTo(0, thirdFloorVgPositionDistance); break; case 3: scrollView.smoothScrollTo(0, fourthFloorVgPositionDistance); break; default: break; } } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); scrollView.setScrollViewListener(this); scrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.d(TAG, "scrollView onTouch"); tabInterceptTouchEventTag = false;//让scrollview处理滑动 return false; } }); } @Override public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) { if (tabInterceptTouchEventTag) {//让tab来处理滑动 return; } Log.d(TAG, "当前scrollView的位置——>" + y); if (y < secondFloorVgPositionDistance) { if (currentPosition != 0) { scrollView.computeScroll(); tabLayout.getTabAt(0).select(); } } else if (y < thirdFloorVgPositionDistance) { if (currentPosition != 1) { scrollView.computeScroll(); tabLayout.getTabAt(1).select(); } } else if (y < fourthFloorVgPositionDistance) { if (currentPosition != 2) { scrollView.computeScroll(); tabLayout.getTabAt(2).select(); } } else { if (currentPosition != 3) { scrollView.computeScroll(); tabLayout.getTabAt(3).select(); } } }}
a. tabInterceptTouchEventTag 作为标志位是为了防止因scrollview触发了tab Selected从而再次引起scrollview滑动导致的滑动不流畅。
b. wrapperFl的存在则是要去给 tabInterceptTouchEventTag 赋值,因为TabLayout的Touch、Click、Focus等事件被消化掉了,无法在这些事件中监听到对应的值的变化,所以通过wrapperFl来进行Touch事件的监听。
c. ObservableScrollView 是继承自Scrollview,新增和改变了其中的以下方法:
public void setScrollViewListener(ScrollViewListener scrollViewListener) { this.scrollViewListener = scrollViewListener; } @Override protected void onScrollChanged(int x, int y, int oldx, int oldy) { super.onScrollChanged(x, y, oldx, oldy); if (scrollViewListener != null) { scrollViewListener.onScrollChanged(this, x, y, oldx, oldy); } } public interface ScrollViewListener { void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy); }
这样就可以在activity主界面中监听到scrollview的滑动事件,从而获取当前整个scrollview所处的位置,进而去判定是否需要选定对应的tab。
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!
喜欢 | 0
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号