android 嵌套滑动

来源:互联网 发布:淘宝介入卖家没有发票 编辑:程序博客网 时间:2024/05/16 17:19

转载自hongyang blog:http://blog.csdn.net/lmj623565791/article/details/52204039

稍微改动了源码,因为要做的效果有点差别:实际效果为米多财富app产品中心首页(目前线上的app虽然实现了效果,但是快速滑动,有时会有bug),所以想要换一种思路解决,就是接下来要讨论的内容。——嵌套滑动

android 5.0之后,引入了几个类:

NestedScrollingChild
NestedScrollingParent
NestedScrollingChildHelper
NestedScrollingParentHelper
             ——v4包已经向下兼容,详细用法可以谷歌。
源码:
主要改动了
StickyNavLayout类的内容,其他类没有修改
package com.zhy.stickynavlayout.view;import android.content.Context;import android.support.v4.view.NestedScrollingParent;import android.support.v4.view.ViewCompat;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.OverScroller;import com.zhy.stickynavlayout.R;public class StickyNavLayout extends LinearLayout implements NestedScrollingParent{    //每次事件会调用一次    @Override    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes)    {        return true;    }    @Override    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes)    {    }    @Override    public void onStopNestedScroll(View target)    {        //getScrollY()的范围在0和mTopViewHeight/2之间            if(getScrollY()<=mTopViewHeight/4)//自动滑下来            {               mScroller.startScroll(0,getScrollY(),0,-getScrollY(),500);            }            else            {                mScroller.startScroll(0,getScrollY(),0,mTopViewHeight/2-getScrollY(),500);            }        postInvalidate();    }    @Override    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)    {    }    @Override    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed)    {        //dy向上移动为正,向下移动为负        boolean hiddenTop = dy > 0 && getScrollY() < mTopViewHeight/2;//为true表示还没有被隐藏        boolean showTop = dy < 0 && getScrollY() >= 0 && !ViewCompat.canScrollVertically(target, -1);//为true表示不能再往下滑动了        //target滑动的时候为true,        if (hiddenTop || showTop)//表示头部还没有完全隐藏        {            scrollBy(0, dy);            consumed[1] = dy;        }    }    @Override    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed)    {        return false;    }    @Override    public boolean onNestedPreFling(View target, float velocityX, float velocityY)    {        //down - //up+        if (getScrollY() >= mTopViewHeight/2) return false;        fling((int) velocityY);//没演示出什么作用        return true;    }    @Override    public int getNestedScrollAxes()    {        return 0;    }    private View mTop;    private View mNav;    private ViewPager mViewPager;    private int mTopViewHeight;    private OverScroller mScroller;    public StickyNavLayout(Context context, AttributeSet attrs)    {        super(context, attrs);        setOrientation(LinearLayout.VERTICAL);        mScroller = new OverScroller(context);    }    @Override    protected void onFinishInflate()    {        super.onFinishInflate();        mTop = findViewById(R.id.id_stickynavlayout_topview);        mNav = findViewById(R.id.id_stickynavlayout_indicator);        View view = findViewById(R.id.id_stickynavlayout_viewpager);        if (!(view instanceof ViewPager))        {            throw new RuntimeException(                    "id_stickynavlayout_viewpager show used by ViewPager !");        }        mViewPager = (ViewPager) view;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)    {        //目的是防止滑动到顶部之后底部出现空白        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));        //重新设置viewpager的高度        ViewGroup.LayoutParams params = mViewPager.getLayoutParams();        params.height = getMeasuredHeight() - mNav.getMeasuredHeight()-mTop.getMeasuredHeight()/2;        //重新设置高度,使不会出现底部空白        setMeasuredDimension(getMeasuredWidth(), mTop.getMeasuredHeight() + mNav.getMeasuredHeight() + mViewPager.getMeasuredHeight());    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh)    {        super.onSizeChanged(w, h, oldw, oldh);        mTopViewHeight = mTop.getMeasuredHeight();    }    public void fling(int velocityY)    {        mScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, mTopViewHeight);        invalidate();    }    @Override    public void scrollTo(int x, int y)    {        if (y < 0)        {            y = 0;        }        if (y > mTopViewHeight/2)        {            y = mTopViewHeight/2;        }        if (y != getScrollY())        {            super.scrollTo(x, y);        }    }    @Override    public void computeScroll()    {        if (mScroller.computeScrollOffset())        {            scrollTo(0, mScroller.getCurrY());            invalidate();        }    }}


SimpleViewPagerIndicator类
package com.zhy.stickynavlayout.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;public class SimpleViewPagerIndicator extends LinearLayout{private static final int COLOR_TEXT_NORMAL = 0xFF000000;private static final int COLOR_INDICATOR_COLOR = Color.GREEN;private String[] mTitles;private int mTabCount;private int mIndicatorColor = COLOR_INDICATOR_COLOR;private float mTranslationX;private Paint mPaint = new Paint();private int mTabWidth;public SimpleViewPagerIndicator(Context context){this(context, null);}public SimpleViewPagerIndicator(Context context, AttributeSet attrs){super(context, attrs);mPaint.setColor(mIndicatorColor);mPaint.setStrokeWidth(9.0F);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh){super.onSizeChanged(w, h, oldw, oldh);mTabWidth = w / mTabCount;}public void setTitles(String[] titles){mTitles = titles;mTabCount = titles.length;generateTitleView();}public void setIndicatorColor(int indicatorColor){this.mIndicatorColor = indicatorColor;}@Overrideprotected void dispatchDraw(Canvas canvas){super.dispatchDraw(canvas);canvas.save();canvas.translate(mTranslationX, getHeight() - 2);canvas.drawLine(0, 0, mTabWidth, 0, mPaint);canvas.restore();}public void scroll(int position, float offset){/** * <pre> *  0-1:position=0 ;1-0:postion=0; * </pre> */mTranslationX = getWidth() / mTabCount * (position + offset);invalidate();}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev){return super.dispatchTouchEvent(ev);}private void generateTitleView(){if (getChildCount() > 0)this.removeAllViews();int count = mTitles.length;setWeightSum(count);for (int i = 0; i < count; i++){TextView tv = new TextView(getContext());LayoutParams lp = new LayoutParams(0,LayoutParams.MATCH_PARENT);lp.weight = 1;tv.setGravity(Gravity.CENTER);tv.setTextColor(COLOR_TEXT_NORMAL);tv.setText(mTitles[i]);tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);tv.setLayoutParams(lp);tv.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){}});addView(tv);}}}


MainActivity类
package com.zhy.stickynavlayout;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.support.v4.view.ViewPager.OnPageChangeListener;import com.zhy.stickynavlayout.view.SimpleViewPagerIndicator;public class MainActivity extends FragmentActivity{private String[] mTitles = new String[] { "简介", "评价", "相关" };private SimpleViewPagerIndicator mIndicator;private ViewPager mViewPager;private FragmentPagerAdapter mAdapter;private TabFragment[] mFragments = new TabFragment[mTitles.length];@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();initDatas();initEvents();}private void initEvents(){mViewPager.setOnPageChangeListener(new OnPageChangeListener(){@Overridepublic void onPageSelected(int position){}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels){mIndicator.scroll(position, positionOffset);}@Overridepublic void onPageScrollStateChanged(int state){}});}private void initDatas(){mIndicator.setTitles(mTitles);for (int i = 0; i < mTitles.length; i++){mFragments[i] = (TabFragment) TabFragment.newInstance(mTitles[i]);}mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){@Overridepublic int getCount(){return mTitles.length;}@Overridepublic Fragment getItem(int position){return mFragments[position];}};mViewPager.setAdapter(mAdapter);mViewPager.setCurrentItem(0);}private void initViews(){mIndicator = (SimpleViewPagerIndicator) findViewById(R.id.id_stickynavlayout_indicator);mViewPager = (ViewPager) findViewById(R.id.id_stickynavlayout_viewpager);}}

TabFragment类
package com.zhy.stickynavlayout;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import com.zhy.base.adapter.ViewHolder;import com.zhy.base.adapter.recyclerview.CommonAdapter;import java.util.ArrayList;import java.util.List;public class TabFragment extends Fragment{    public static final String TITLE = "title";    private String mTitle = "Defaut Value";    private RecyclerView mRecyclerView;    // private TextView mTextView;    private List<String> mDatas = new ArrayList<String>();    @Override    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        if (getArguments() != null)        {            mTitle = getArguments().getString(TITLE);        }    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState)    {        View view = inflater.inflate(R.layout.fragment_tab, container, false);        mRecyclerView = (RecyclerView) view                .findViewById(R.id.id_stickynavlayout_innerscrollview);        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));        // mTextView = (TextView) view.findViewById(R.id.id_info);        // mTextView.setText(mTitle);        for (int i = 0; i < 50; i++)        {            mDatas.add(mTitle + " -> " + i);        }        mRecyclerView.setAdapter(new CommonAdapter<String>(getActivity(), R.layout.item, mDatas)        {            @Override            public void convert(ViewHolder holder, String o)            {                holder.setText(R.id.id_info, o);            }        });        return view;    }    public static TabFragment newInstance(String title)    {        TabFragment tabFragment = new TabFragment();        Bundle bundle = new Bundle();        bundle.putString(TITLE, title);        tabFragment.setArguments(bundle);        return tabFragment;    }}

activity_main.xml类
<com.zhy.stickynavlayout.view.StickyNavLayout xmlns:tools="http://schemas.android.com/tools"    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <RelativeLayout        android:id="@id/id_stickynavlayout_topview"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="#4400ff00" >        <TextView            android:layout_width="match_parent"            android:layout_height="256dp"            android:gravity="center"            android:text="软件介绍"            android:textSize="30sp"            android:textStyle="bold" />    </RelativeLayout>    <com.zhy.stickynavlayout.view.SimpleViewPagerIndicator        android:id="@id/id_stickynavlayout_indicator"        android:layout_width="match_parent"        android:layout_height="50dp"        android:background="#ffffffff" >    </com.zhy.stickynavlayout.view.SimpleViewPagerIndicator>    <android.support.v4.view.ViewPager        android:id="@id/id_stickynavlayout_viewpager"        android:layout_width="match_parent"        android:layout_height="match_parent"         >    </android.support.v4.view.ViewPager></com.zhy.stickynavlayout.view.StickyNavLayout >




fragment_tab.xml
<android.support.v7.widget.RecyclerView android:id="@id/id_stickynavlayout_innerscrollview"                                        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:background="#44ff0000"                                        android:scrollbars="none"></android.support.v7.widget.RecyclerView>

item.xml
<?xml version="1.0" encoding="utf-8"?><FrameLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="50dp">    <TextView        android:id="@+id/id_info"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#ffffffff"        android:gravity="center">    </TextView></FrameLayout>




0 0