当前位置: 移动技术网 > 移动技术>移动开发>Android > Android 仿支付宝城市服务栏目tab选择滑动子View效果

Android 仿支付宝城市服务栏目tab选择滑动子View效果

2018年12月28日  | 移动技术网移动技术  | 我要评论

一. 图示

\

支付宝效果
\实现的效果

二. 思路讲解

tablayout+scrollview实现即可。每一个tab对应scrollview中包裹的一层布局,以上有4个tab,也就需要inflate 4个布局文件,用来表示每一层的样式内容。

1.页面加载完毕后,记住每一层父布局在screen中所要滑动至顶部的距离distance;

2.操作:

a. 当点击tab时:滑动scrollview该层的距离distance;

b. 当滑动scrollview至对应的层时: 选定对应的tab。

三. 代码

1. 布局代码




    <framelayout android:layout_height="wrap_content" android:layout_width="match_parent">

        

        <framelayout android:id="@+id/wrapperfl" android:layout_height="match_parent" android:layout_width="match_parent"></framelayout>
    </framelayout>

    

        

        

    
 

布局代码很简单,可能会有的疑问点有:

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网