android仿制应用宝的应用详情页

这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述

最近看到了应用宝的软件详情页,感觉不明觉厉的样子,
这里写图片描述

于是粗略的仿制了一下,发现做的还算是可以出来见人吧这里写图片描述

这里写图片描述

实现方法很简单,就是通过重写ScrollView的分发事件,详情请看代码。

这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述这里写图片描述

public class MultiScrollView extends ScrollView{

    Scroller mScroller;
    ViewGroup mChid;
    private Toolbar mToolbar;
    View destineView;
    View firstChid;
    View secondChid;
    View thirdChid;
    float startY;


    public MultiScrollView(Context context) {
        this(context,null,0);
    }

    public MultiScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MultiScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScroller = new Scroller(context);
    }


    //设置toolbar
    public void setToolbar(Toolbar toolbar){
        this.mToolbar = toolbar;
    }
    //设置listview,
    public void setDestineView(View view){
        this.destineView = view;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mChid = (ViewGroup) getChildAt(0);
        //判断scrollview是否有三个孙view,是的话将第三个(默认认为是listview)调整高度
        if(mChid != null && mChid.getChildCount() == 3 && (getHeight() - mChid.getChildAt(1).getMeasuredHeight() != mChid.getChildAt(2).getMeasuredHeight())){

            firstChid = mChid.getChildAt(0);
            secondChid = mChid.getChildAt(1);
            thirdChid = mChid.getChildAt(2);
            //listview高度调整为listview高度+导航条高度+toolbar高度 = scrollview高度(getHeight),这样scrollview最多刚好滚动到除了导航条+toolbar,其余的都是listview
            int listviewHeight = getHeight() - secondChid.getMeasuredHeight() - (mToolbar == null ?  0 : mToolbar.getMeasuredHeight());
            thirdChid.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, listviewHeight));
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        //设置背景颜色渐变
        if(mToolbar!= null && firstChid != null){
            int alpha = t * 255/ (firstChid.getMeasuredHeight()/2) ;
            mToolbar.getBackground().setAlpha(Math.min(255,alpha));
        }
    }

    //父类Scrollview在onInterceptTouchEvent实现滑动逻辑,故重写此方法
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        if(destineView == null || mChid == null || mChid.getChildCount() != 3){
            return super.onInterceptTouchEvent(ev);
        }

        //listview可向上滚动,将点击事件分发给listview
        if(destineView.canScrollVertically(-1)){
            return false;
        }

        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                startY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float offsetY = ev.getY() - startY;

                //向下滚动
                if(offsetY < 0){
                    //scrollview刚好滚动到除了导航条+toolbar,其余的都是listview的时候,在向下滚动的时候就滚动listview,
                    // 注意getScrollY不会随着touch move而改变,滚动的时候getScrollY()一直保持不变;所以你从其他位置滚动到临界值的时候不会分发事件,从临界值再次滚动是才会符合条件
                    if(getScrollY() >= mChid.getChildAt(0).getMeasuredHeight()-(mToolbar == null ? 0 : mToolbar.getMeasuredHeight())){
                        return false;
                    }
                }
                //向上滚动
                else if(offsetY > 0){
                    //listview滚动到头了,再向上滚动,会自动滚动到scrollview顶部(0,0);
                    if(getScrollY() == firstChid.getMeasuredHeight()-(mToolbar == null ? 0 : mToolbar.getMeasuredHeight())){
                        //缓慢的滚动到顶部^^^^^^
                        mScroller.startScroll(0,getScrollY(),0,-getScrollY(),1000);
                    }
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            int currY = mScroller.getCurrY();
            scrollTo(0,currY);
            invalidate();
        }
    }
}

上面Scrollview,我将他的孙view定为3个,第一个view算是banner页,第二个是导航条,第三个是包裹listview的viewpager,因为scrollview下的listview设置高度有点蛋疼,所以就在onLayout中设置它的高度,最终的第三个view的高度为scrollview的高度减去toolbar和导航栏的高度。
然后在onInterceptTouchEvent处理事件,返回false时将事件交给它的子控件处理,大体就是这一些逻辑,这里写图片描述

对布局文件有一些要求,要求只能用三个孙控件,布局文件有一点需要小注意

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.tian.myapplication.listview.Main2Activity">

    <com.example.tian.myapplication.github.MultiScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollView">

        <!--android:focusable="true"
            android:focusableInTouchMode="true"
            这里添加这两个,否则scrollview初始化完会自动滚动到viewpager那里-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:orientation="vertical">
            <!--三层三层三层三层三层三层三层三层三层三层三层 view-->
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:background="#28c8f4">

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_launcher"
                    android:id="@+id/imageview"
                    android:layout_centerInParent="true"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/imageview"
                    android:layout_marginTop="10dp"
                    android:text="HELLO WOELD"
                    android:textSize="20sp"
                    android:textColor="#ff0000"
                    android:layout_centerHorizontal="true"/>

            </RelativeLayout>

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
                <android.support.design.widget.TabLayout
                    xmlns:app="http://schemas.android.com/apk/res-auto"
                    android:id="@+id/tablayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:tabTextColor="#1bccef"/>
            </RelativeLayout>

            <android.support.v4.view.ViewPager
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="#777777"
                android:id="@+id/viewPager"/>

        </LinearLayout>

    </com.example.tian.myapplication.github.MultiScrollView>

    <android.support.v7.widget.Toolbar
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar"
        android:layout_height="50dp"
        android:minHeight="50dp"
        android:layout_width="match_parent"
        android:background="#fe6d18"

        />

</RelativeLayout>

最后附上一些微不住道的代码
http://download.csdn.net/detail/recall2012/9402757

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值