Android5.0 Material design

来源:互联网 发布:淘宝店铺如何免费推广 编辑:程序博客网 时间:2024/06/11 11:37

        在界面开发过程中,我们经常遇到子控件的移动到某一阶段,引起父控件或者其他控件产生动态效果;

        在android 5.0 的Material design设计中,就为我们封装了一套这样的接口,即 NestedScrollingParent 和 NestedScrollingChild;

原理比较简单,当子控件需要滑动的时候,即调用startNestedScroll方法,在滑动之前,可以调用dispatchNestedPreScroll方法,来告诉父view是否需要滑动;
那么子view和父view是如果做到沟通的尼,这就需要第三个类来帮忙了 —- NestedScrollingChildHelper

下面的代码实现了 向左边滑动文字,当文字超过边界的时候, 图片收缩
这里写图片描述

package com.migu.hwj.component;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.support.v4.view.NestedScrollingChild;import android.support.v4.view.NestedScrollingChildHelper;import android.support.v4.view.NestedScrollingParent;import android.support.v4.view.NestedScrollingParentHelper;import android.support.v4.view.ViewCompat;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;import com.migu.hwj.as.leanring.R;import com.migu.hwj.util.MyLog;/* *  演示Android5.0中Material design设计总新增的一些控件和Api * *  同时这个类也演示了在XML中如何使用内部类,即在xml中使用内部类有两个注意的地方 *  1: 内部类是static的,public private没关系 *  2:在xml中控件需要使用view这样的标签,并以class标签描述类的完整路径,以$链接内部类 * *  参考:http://blog.csdn.net/gorgle/article/details/51428515 *//* * NestedScrolling机制 * 作用: 让父View和子View在滚动式进行配合,实现诸如子view滑动一定距离,父view是如何滑动的效果等等 * 主要接口 *     NestedScrollingChild *     NestedScrollingParent * 帮助类 *   NestedScrollingChildHelper *   NestedScrollingParentHelper * * 子view一般继承NestedScrollingChild接口作为动作的发起者, 父view一般继承NestedScrollingParent作用动作的响应者 * 正因为这种关系,因此当继承NestedScrollingChild接口的子view一些方法触发的时候,继承NestedScrollingParent的父view的一些方法也会被回调 * * 例如: * 子view的startNestedScroll会触发父view的onStartNestedScroll * */public class KitkatActivity extends Activity {    private KitKatNestedScrollingParent mKitKatNestedScrollingParent;    private LinearLayout.LayoutParams mKitNetedParentParams;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_nested_scrolling);    }    /*     * Android5.0中Material design设计中配合子view滑动的父控件     */    public static class KitKatNestedScrollingParent extends LinearLayout implements NestedScrollingParent {        private NestedScrollingParentHelper mNestedScrollingParentHelper;        public KitKatNestedScrollingParent(Context context) {            super(context);            init();        }        public KitKatNestedScrollingParent(Context context, AttributeSet attrs) {            super(context, attrs);            init();        }        private void init() {            mNestedScrollingParentHelper = new NestedScrollingParentHelper(this);        }        //因为实现NestedScrollingParent接口,而实现的方法        /**         * 回调开始滑动  该方法决定了当前控件是否能接收到其内部View滑动时的参数         *         * @param child            该父VIew 的子View         * @param target           支持嵌套滑动的 VIew         * @param nestedScrollAxes 滑动方向         * @return 是否支持 嵌套滑动         */        @Override        public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {            MyLog.logD("KitKatNestedScrollingParent onStartNestedScroll");            if (target instanceof KitKatNestedScrollingChild) {                return true;            }            return false;        }        //因为实现NestedScrollingParent接口,而实现的方法        @Override        public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {            MyLog.logD("KitKatNestedScrollingParent onNestedScrollAccepted");            mNestedScrollingParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes);        }        //因为实现NestedScrollingParent接口,而实现的方法        @Override        public void onStopNestedScroll(View target) {            MyLog.logD("KitKatNestedScrollingParent onStopNestedScroll");            mNestedScrollingParentHelper.onStopNestedScroll(target);        }        //因为实现NestedScrollingParent接口,而实现的方法        @Override        public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {            MyLog.logD("KitKatNestedScrollingParent onNestedScroll");        }        //因为实现NestedScrollingParent接口,而实现的方法        /*         * 该方法的会传入内部View移动的dx,dy 前3个为输入参数,最后一个是输出参数         * consumed : The horizontal and vertical scroll distance consumed by this parent         * 向上滑动 dy > 0, dx应该等于0(如果X坐标没有发生变化)         * 向下滑动 dy < 0, dx应该等于0(如果X坐标没有发生变化)         * 向左滑动 dx > 0, dy应该等于0(如果y坐标没有发生变化)         * 向右滑动 dx < 0, dy应该等于0(如果y坐标没有发生变化)         *         * @param target View that initiated the nested scroll         * @param dx Horizontal scroll distance in pixels         * @param dy Vertical scroll distance in pixels         * @param consumed Output. The horizontal and vertical scroll distance consumed by this parent         */        @Override        public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {            MyLog.logD("KitKatNestedScrollingParent onNestedPreScroll dx " + dx);            if (dx > 0) {                scrollBy(dx,0);//滚动                consumed[0] = dx;//告诉child我消费了多少            }        }        //因为实现NestedScrollingParent接口,而实现的方法        /*         * 捕获对内部View的fling事件,如果return true则表示拦截掉内部View的事件         */        @Override        public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {            MyLog.logD("KitKatNestedScrollingParent onNestedFling");            return false;        }        //因为实现NestedScrollingParent接口,而实现的方法        @Override        public boolean onNestedPreFling(View target, float velocityX, float velocityY) {            MyLog.logD("KitKatNestedScrollingParent onNestedPreFling");            return false;        }        //因为实现NestedScrollingParent接口,而实现的方法        @Override        public int getNestedScrollAxes() {            MyLog.logD("KitKatNestedScrollingParent getNestedScrollAxes");            return mNestedScrollingParentHelper.getNestedScrollAxes();        }        //scrollBy内部会调用scrollTo        @Override        public void scrollTo(int x, int y) {            super.scrollTo(x, y);        }        @Override        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {            super.onMeasure(widthMeasureSpec, heightMeasureSpec);        }        @Override        protected void onLayout(boolean changed, int l, int t, int r, int b) {            super.onLayout(changed, l, t, r, b);        }    }    /*     * Android5.0中Material design设计中子view控件     */    public static class KitKatNestedScrollingChild extends LinearLayout implements NestedScrollingChild {        //NestedScrolling帮助类,这个类似ontouch里面使用了手势识别帮助类        private NestedScrollingChildHelper mNestedScrollingChildHelper;        //上一次水平滑动距离        private int lastX;        private final int[] offset = new int[2];   //偏移量        private final int[] consumed = new int[2]; //消费        //子view宽        private int childWidth;        public KitKatNestedScrollingChild(Context context) {            super(context);        }        public KitKatNestedScrollingChild(Context context, AttributeSet attrs) {            super(context, attrs);        }        /**         * 设置嵌套滑动是否可用         *         * @param enabled 参数enabled:true表示view使用嵌套滚动,false表示禁用.         */        @Override        public void setNestedScrollingEnabled(boolean enabled) {            MyLog.logD("KitKatNestedScrollingChild getNestedScrollAxes");            getScrollingChildHelper().setNestedScrollingEnabled(enabled);        }        /**         * 嵌套滑动是否可用         *         * @return         */        @Override        public boolean isNestedScrollingEnabled() {            MyLog.logD("KitKatNestedScrollingChild isNestedScrollingEnabled");            return getScrollingChildHelper().isNestedScrollingEnabled();        }        /**         * 开始嵌套滑动,         *         * @param axes 表示方向 有一下两种值         *             ViewCompat.SCROLL_AXIS_HORIZONTAL 横向哈东         *             ViewCompat.SCROLL_AXIS_VERTICAL 纵向滑动         *             <p>         *             返回值:true表示本次滚动支持嵌套滚动,false不支持         */        @Override        public boolean startNestedScroll(int axes) {            MyLog.logD("KitKatNestedScrollingChild startNestedScroll");            return getScrollingChildHelper().startNestedScroll(axes);        }        @Override        public void stopNestedScroll() {            MyLog.logD("KitKatNestedScrollingChild stopNestedScroll");            getScrollingChildHelper().stopNestedScroll();        }        /**         * 是否有父View 支持 嵌套滑动,  会一层层的网上寻找父View         *         * @return         */        @Override        public boolean hasNestedScrollingParent() {            MyLog.logD("KitKatNestedScrollingChild hasNestedScrollingParent");            return getScrollingChildHelper().hasNestedScrollingParent();        }        /**         * 在处理滑动之后 调用         *         * @param dxConsumed     表示view消费了x方向的距离长度         * @param dyConsumed     表示view消费了y方向的距离长度         * @param dxUnconsumed   表示滚动产生的x滚动距离还剩下多少没有消费         * @param dyUnconsumed   表示滚动产生的y滚动距离还剩下多少没有消费         * @param offsetInWindow 表示剩下的距离dxUnconsumed和dyUnconsumed使得view在父布局中的位置偏移了多少         * @return         */        @Override        public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {            MyLog.logD("KitKatNestedScrollingChild dispatchNestedScroll");            return getScrollingChildHelper().dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);        }        /**         * 一般在滑动之前调用, 在ontouch 中计算出滑动距离, 然后调用该方法, 就给支持的嵌套的父View 处理滑动事件         *         * @param dx             x 轴上滑动的距离, 相对于上一次事件, 不是相对于 down事件的 那个距离         * @param dy             y 轴上滑动的距离         * @param consumed       表示父布局消费的距离 一个数组, 可以传 一个空的 数组,  表示 x 方向 或 y 方向的事件 是否有被消费  consumed[0]表示x方向,consumed[1]表示y方向         * @param offsetInWindow 支持嵌套滑动到额父View 消费 滑动事件后 导致 本 View 的移动距离         * @return 支持的嵌套的父View 是否处理了 滑动事件         */        @Override        public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {            MyLog.logD("KitKatNestedScrollingChild dispatchNestedPreScroll");            return getScrollingChildHelper().dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);        }        /**         * @param velocityX x 轴上的滑动速度         * @param velocityY y 轴上的滑动速度         * @param consumed  是否被消费         * @return         */        @Override        public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {            MyLog.logD("KitKatNestedScrollingChild dispatchNestedFling");            return getScrollingChildHelper().dispatchNestedFling(velocityX, velocityY, consumed);        }        /**         * @param velocityX x 轴上的滑动速度         * @param velocityY y 轴上的滑动速度         * @return         */        @Override        public boolean dispatchNestedPreFling(float velocityX, float velocityY) {            MyLog.logD("KitKatNestedScrollingChild dispatchNestedPreFling");            return getScrollingChildHelper().dispatchNestedPreFling(velocityX, velocityY);        }        @Override        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {            super.onMeasure(widthMeasureSpec, heightMeasureSpec);            childWidth = this.getMeasuredWidth();            MyLog.logD("KitKatNestedScrollingChild onMeasure childWidth " + childWidth);        }        @Override        public boolean onTouchEvent(MotionEvent event) {            switch (event.getAction()) {                //按下                case MotionEvent.ACTION_DOWN:                    lastX = (int) event.getRawX();                    break;                //移动                case MotionEvent.ACTION_MOVE:                    int x = (int) (event.getRawX());                    int dx = x - lastX;                    lastX = x;                    scrollBy(-dx, 0);                    break;            }            return true;        }        //限制滚动范围        @Override        public void scrollTo(int x, int y) {            super.scrollTo(x, y);            //当超出内容显示的时候,通知父控制收放imageview            MyLog.logD("KitKatNestedScrollingChild scrollTo  x " + x  + " lastX  " + lastX);            //向左滑            if(x >= childWidth && x > 0){                //startNestedScroll开始滑动  dispatchNestedPreScroll 通知父控件滑动                startNestedScroll(ViewCompat.SCROLL_AXIS_HORIZONTAL);                dispatchNestedPreScroll(lastX, 0, consumed, offset);            }        }        //初始化helper对象        private NestedScrollingChildHelper getScrollingChildHelper() {            if (mNestedScrollingChildHelper == null) {                mNestedScrollingChildHelper = new NestedScrollingChildHelper(this);                mNestedScrollingChildHelper.setNestedScrollingEnabled(true);            }            return mNestedScrollingChildHelper;        }    }}
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              xmlns:tools="http://schemas.android.com/tools"              android:layout_width="match_parent"              android:orientation="horizontal"              android:layout_height="match_parent"    >    <view        class="com.migu.hwj.component.KitkatActivity$KitKatNestedScrollingParent"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true"        android:layout_alignParentTop="true"        android:orientation="horizontal">h        <ImageView            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:src="@mipmap/ic_launcher"/>        <view            class="com.migu.hwj.component.KitkatActivity$KitKatNestedScrollingChild"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical">            <TextView                android:layout_width="match_parent"                android:layout_height="match_parent"                android:text="向左滑动可以收缩左边的图片"                android:gravity="center"                android:textColor="#f0f"                android:textSize="20sp"/>        </view>        -->    </view></LinearLayout>
package com.migu.hwj.util;import android.util.Log;public class MyLog{    private static boolean mOpenLog = true;    private static String mTag = "hwj";    public static void setTag(String tag){        mTag = tag;    }    public static void logD(String message){        if(mOpenLog){            Log.d(mTag,message);        }    }}
原创粉丝点击