Android_滑动的时候头部变化效果

来源:互联网 发布:mac口红市场占有率 编辑:程序博客网 时间:2024/04/30 09:07

废话少说,直接上图哦

先看看上面的布局,从上到下:头部使用相对布局,然后是三个选项,然后线性布局里面装的fragment,fragment里面又是可以上啦刷新的listview。我的思路是准备在activity里面直接实现。activtiy里面有两个处理事件的方法

onTouchEvent(MotionEvent event)
dispatchTouchEvent(MotionEvent ev)

这两个事件选哪个合适呢?肯定是选第二个赛,选第一个的话肯定实现不起效果,因为事件传递(不懂百度),就被listview消耗了。

下面进入正题:

第一步:滚动的时候试着改变头部的高度

第二步:逐渐让周围不需要的字体消失

第三步:根据偏移率计算偏移量,然后把图片和需要的文字移动到顶端中心处

先声明需要用到的数据,下面全部列举出来

private int mLastY = 0;  //最后的点private static int mNeedDistance;   // 需要滑动的距离private static int mMinHight; //最小高度private static int mOrignHight; //原始的高度private int mCurrentDistance = 0;  //当前的距离private float mRate = 0;  //距离与目标距离的变化率 mRate=mCurrentDistance/mNeedDistanceprivate int mPhotoOriginHeight; //图片的原始高度private int mPhotoOriginWidth; //图片的原始宽度private int mPhotoLeft;  //图片距左边的距离private int mPhotoTop;  //图片距离上边的距离private int mPhotoNeedMoveDistanceX;  // 图片需要移动的X距离private int mPhotoNeedMoveDistanceY;  // 图片需要移动的Y距离//需要移动的文字private int mTextLeft;  //文字距左边的距离private int mTextTop;  //文字距离上边的距离private int mTextNeedMoveDistanceX;  // 文字需要移动的X距离private int mTextNeedMoveDistanceY;  //文字需要移动的Y距离/** * 初始化需要滚动的距离 */private void initDistance() {    mOrignHight = rl_head.getLayoutParams().height;    mMinHight = UIUtils.dip2px(this, 45);  //设置最小的高度为这么多    mNeedDistance = mOrignHight - mMinHight;    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) img_head_portrait.getLayoutParams();    mPhotoOriginHeight = params.height;    mPhotoOriginWidth = params.width;    mPhotoLeft = params.leftMargin;    mPhotoTop = params.topMargin;    mPhotoNeedMoveDistanceX = UIUtils.getWindowWidth(this) / 2 - mPhotoLeft - mMinHight;    mPhotoNeedMoveDistanceY = mPhotoTop - UIUtils.dip2px(this, 10);    /*******************移动的文字初始化***************************/    RelativeLayout.LayoutParams textParams = (RelativeLayout.LayoutParams) tv_user_name.getLayoutParams();    mTextLeft = textParams.leftMargin;    mTextTop = textParams.topMargin;    mTextNeedMoveDistanceX = UIUtils.getWindowWidth(this) / 2 - mTextLeft + 10;    mTextNeedMoveDistanceY = mTextTop - mMinHight / 2 / 2;  //这里计算有点误差,正确的应该是剪去获取textview高度的一半}

实现第一步操作:

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {    switch (ev.getAction()) {        case MotionEvent.ACTION_DOWN:            mLastY = (int) ev.getY();            LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);            return super.dispatchTouchEvent(ev); //传递事件 例如可以用来子view的点击事件等        case MotionEvent.ACTION_MOVE:            int y = (int) ev.getY();            int dy = mLastY - y;            LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);            if (mCurrentDistance >= mNeedDistance && dy > 0) {                return super.dispatchTouchEvent(ev);  //传递事件            }            if (mCurrentDistance <= 0 && dy < 0) {                return super.dispatchTouchEvent(ev); //把事件传递进去            }            //改变布局            changeTheLayout(dy);              mLastY = y;            break;        case MotionEvent.ACTION_UP:            checkTheHeight();            LogUtils.d(TAG, "ACTION_MOVE==mCurrentDistance" + mCurrentDistance);            return super.dispatchTouchEvent(ev);    }    return false;}

改变布局的大小的:

/** * 通过滑动的偏移量 * * @param dy */private void changeTheLayout(int dy) {    final ViewGroup.LayoutParams layoutParams = rl_head.getLayoutParams();    layoutParams.height = layoutParams.height - dy;    rl_head.setLayoutParams(layoutParams);    checkTheHeight();    rl_head.requestLayout();    //计算当前移动了多少距离    mCurrentDistance = mOrignHight - rl_head.getLayoutParams().height;    mRate = (float) (mCurrentDistance * 1.0 / mNeedDistance);    changeTheAlphaAndPostion(mRate);  //获取偏移率然后改变某些控件的透明度,和位置    LogUtils.d(TAG, "ACTION_MOVE==dy" + dy);}

获取了偏移率(0.0-1.0),然后就可以根据这个改变透明度了和大小了。

/** * 根据变化率来改变这些这些控件的变化率位置 * * @param rate */private void changeTheAlphaAndPostion(float rate) {    //先改变一些控件的透明度    if (rate >= 1) {        tv_user_hosipital.setVisibility(View.GONE);        tv_user_hosipital_level.setVisibility(View.GONE);        tv_user_project.setVisibility(View.GONE);    } else {        tv_user_hosipital.setVisibility(View.VISIBLE);        tv_user_hosipital_level.setVisibility(View.VISIBLE);        tv_user_project.setVisibility(View.VISIBLE);        tv_user_hosipital.setAlpha(1 - rate);        tv_user_hosipital_level.setAlpha(1 - rate);        tv_user_project.setAlpha(1 - rate);        tv_user_hosipital.setScaleY(1 - rate);        tv_user_hosipital.setScaleX(1 - rate);        tv_user_hosipital_level.setScaleY(1 - rate);        tv_user_hosipital_level.setScaleX(1 - rate);        tv_user_project.setScaleY(1 - rate);        tv_user_project.setScaleX(1 - rate);    }    //接下来是改变控件的大小和位置了  (这就是关键了)    final RelativeLayout.LayoutParams photoParams = (RelativeLayout.LayoutParams) img_head_portrait.getLayoutParams();    photoParams.width = (int) (mPhotoOriginWidth - (rate * (mPhotoOriginWidth - mMinHight - UIUtils.dip2px(this, 10))));    photoParams.height = (int) (mPhotoOriginWidth - (rate * (mPhotoOriginWidth - mMinHight - UIUtils.dip2px(this, 10))));    photoParams.leftMargin = (int) (mPhotoLeft + mPhotoNeedMoveDistanceX * rate);    photoParams.topMargin = (int) (mPhotoTop - mPhotoNeedMoveDistanceY * rate);    LogUtils.d(TAG, "photoParams.leftMargin" + photoParams.leftMargin);    LogUtils.d(TAG, " photoParams.topMargin" + photoParams.topMargin);    img_head_portrait.setLayoutParams(photoParams);    /*********************文字设置****************************/    final RelativeLayout.LayoutParams textParams = (RelativeLayout.LayoutParams) tv_user_name.getLayoutParams();    textParams.leftMargin = (int) (mTextLeft + mTextNeedMoveDistanceX * rate);    textParams.topMargin = (int) (mTextTop - mTextNeedMoveDistanceY * rate);    LogUtils.d(TAG, "textParams.leftMargin" + textParams.leftMargin);    LogUtils.d(TAG, " textParams.topMargin" + textParams.topMargin);    tv_user_name.setLayoutParams(textParams);}

卧槽,搞忘了一个方法,滑动的时候需要检查边界值;这里写了一个方法:

/** * 检查上边界和下边界 */private void checkTheHeight() {    final ViewGroup.LayoutParams layoutParams = rl_head.getLayoutParams();    if (layoutParams.height < mMinHight) {        layoutParams.height = mMinHight;        rl_head.setLayoutParams(layoutParams);        rl_head.requestLayout();    }    if (layoutParams.height > mOrignHight) {        layoutParams.height = mOrignHight;        rl_head.setLayoutParams(layoutParams);        rl_head.requestLayout();    }}

还有一个关键的地方,布局文件的时候 最好是图片控件和需要移动的文字textview不要依赖于其他控件,不然计算margin很麻烦,所以我布局文件就用了简单粗糙的来实现布局:

需要变化的图片控件
<com.facebook.drawee.view.SimpleDraweeView    android:id="@+id/img_head_portrait"    android:layout_width="90dp"    android:layout_height="90dp"    android:layout_centerVertical="true"    android:layout_marginLeft="@dimen/margin_20dp"    android:padding="1dp"    fresco:fadeDuration="500"    fresco:placeholderImage="@mipmap/icon_user_avatar" />

需要变化的文字控件
<TextView    android:id="@+id/tv_user_name"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginLeft="120dp"  //这个距离直接设置的 ,不要用align。。。这个属性,不然不好计算margin    android:layout_marginTop="@dimen/margin_30dp"  //这个也是一样的道理    android:text="蒋心平"    android:textColor="@color/white"    android:textSize="@dimen/text_size_18" />

差不多就这样就能实现上面的效果了。当做完这个功能的时候,我突然觉得一些主流app,实现的向上滑动,title慢慢消失或者隐藏就so easy了,原理都是一样的。只要对事件分发拦截机制有一点认识都能实现这样的效果了。

6 0
原创粉丝点击