安卓吸顶+下拉放大_两种图片下拉放大效果实现(自定义CoordinatorLayout以及自定义Recylerview)...

本文介绍了如何在安卓中实现两种图片下拉放大效果,包括自定义CoordinatorLayout和自定义RecyclerView的方式。通过重写触摸事件,实现了图片随着下拉放大,松手后回弹动画。详细讲解了代码实现过程和布局结构。
摘要由CSDN通过智能技术生成

一、自定义CoordinatorLayout实现图片放大功能

本文是基于折叠布局实现的图片上拉滑动,下拉图片放大,松手放大的效果,先看下效果图。

实现原理:

1.使用CoordinatorLayout自带效果实现上滑。

2.重写CoordinatorLayout触摸事件,在分发之前判断当前是否是在最顶部,并且是下拉操作。

是:进行图片放大,平移下面布局;松手后执行图片回弹动画,恢复布局。

否:不处理事件,滑动事件自动交给下面的Nestscrollview

代码实现如下:

public class CustomCoordinatorLayout extendsCoordinatorLayout {privateView mZoomView;private intmZoomViewWidth;private intmZoomViewHeight;private float firstPosition;//记录第一次按下的位置

private boolean isScrolling;//是否正在缩放

private boolean isScrollDown;//是否下滑

private float mScrollRate = 0.6f;//缩放系数,缩放系数越大,变化的越大

private float mReplyRate = 0.3f;//回调系数,越大,回调越慢

privateView mMoveView;privateView mMoveView2;private intheight,height2;publicCustomCoordinatorLayout(@NonNull Context context) {super(context);

}publicCustomCoordinatorLayout(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);

}public CustomCoordinatorLayout(@NonNull Context context, @Nullable AttributeSet attrs, intdefStyleAttr) {super(context, attrs, defStyleAttr);

}public voidsetmZoomView(View mZoomView) {this.mZoomView =mZoomView;

}public voidsetmMoveView(View mMoveView1,View mMoveView2) {this.mMoveView =mMoveView1;this.mMoveView2 =mMoveView2;

height=mMoveView.getMeasuredHeight();

height2=mMoveView2.getMeasuredHeight();

}

@Overridepublic booleandispatchTouchEvent(MotionEvent ev) {int[] location = new int[2];

mZoomView.getLocationOnScreen(location);int y = location[1];if (mZoomViewWidth <= 0 || mZoomViewHeight <= 0) {

mZoomViewWidth=mZoomView.getMeasuredWidth();

mZoomViewHeight=mZoomView.getMeasuredHeight();

}switch(ev.getAction()) {caseMotionEvent.ACTION_UP:if(isScrollDown) break;//手指离开后恢复图片

isScrolling = false;

replyImage();break;caseMotionEvent.ACTION_MOVE:if(y != 0) return super.dispatchTouchEvent(ev);

isScrollDown= false;if (!isScrolling) {if (getScrollY() == 0) {

firstPosition= ev.getY();//滚动到顶部时记录位置,否则正常返回

} else{break;

}

}int distance = (int) ((ev.getY() - firstPosition) * mScrollRate); //滚动距离乘以一个系数

if (distance < 0) { //当前位置比记录位置要小,正常返回

isScrollDown = true;break;

}//处理放大

isScrolling = true;

setZoom(distance);return super.dispatchTouchEvent(ev);

}return super.dispatchTouchEvent(ev);

}private void scrollDown(floatzoom) {

mMoveView2.setScrollY(-(int)(height2 * ((height2 + zoom) /height2)));

}//回弹动画

private voidreplyImage() {float distance = mZoomView.getMeasuredWidth() -mZoomViewWidth;

ValueAnimator valueAnimator= ValueAnimator.ofFloat(distance, 0f).setDuration((long) (distance *mReplyRate));

valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Overridepublic voidonAnimationUpdate(ValueAnimator animation) {

setZoom((Float) animation.getAnimatedValue());

}

});

valueAnimator.start();

mMoveView.setScrollY(height);

mMoveView2.setScrollY(height2);

}public void setZoom(floatzoom) {if (mZoomViewWidth <= 0 || mZoomViewHeight <= 0) {return;

}

ViewGroup.LayoutParams lp=mZoomView.getLayoutParams();

lp.width= (int) (mZoomViewWidth * ((mZoomViewWidth + zoom) /mZoomViewWidth));

lp.height= (int) (mZoomViewHeight * ((mZoomViewWidth + zoom) /mZoomViewWidth));

((MarginLayoutParams) lp).setMargins(-(lp.width - mZoomViewWidth) / 2, 0, 0, 0);

mZoomView.setLayoutParams(lp);try{

CollapsingToolbarLayout parent=(CollapsingToolbarLayout) (mMoveView.getParent());

ViewGroup.LayoutParams layoutParams=parent.getLayoutParams();

layoutParams.height=lp.height;

parent.setLayoutParams(layoutParams);

}catch(Exception e){

}

}

}

布局文件结构:

>

//要放大的图片

/>//平移布局一

>

//代码省略

...

//平移布局二

android:id="@+id/ll_layout"

android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"

>//代码省略

...

使用就非常简单了,在代码中设置要放大的view以及需要平移的view就可以了。

privatefun zoomImage() {

cl_layout.setmMoveView(rl_layout,ll_layout)

cl_layout.setmZoomView(mine_iv_avatar)

}

以上只是个例子用于实现特定布局的动画效果,实际应用可根据场景来自定义view进行操作。

二、自定义recylerView实现图片放大效果

实现效果如下:

实现原理:

重写recylerview的onTouchEvent方法,在顶部往下滑的时候,进行第一个item图片放大及布局下移操作。

好处:多布局中自带滑动,不用处理其他item的滑动,流畅程度100%

代码实现如下:

public class ZoomRecyclerView extendsRecyclerView {privateView mZoomView;private intmZoomViewWidth;private intmZoomViewHeight;private intmViewParentHeight;private float mScrollRate = 0.3f;//缩放系数,缩放系数越大,变化的越大

private float mReplyRate = 0.3f;//回调系数,越大,回调越慢//记录首次按下位置

private float mFirstPosition = 0;//是否正在放大

private Boolean mScaling = false;

LinearLayoutManager mLinearLayoutManager ;publicZoomRecyclerView( Context context) {super(context);

}publicZoomRecyclerView( Context context, AttributeSet attrs) {super(context, attrs);

}public ZoomRecyclerView( Context context, AttributeSet attrs, intdefStyleAttr) {super(context, attrs, defStyleAttr);

}public voidsetZoomView(SimpleDraweeView v, LinearLayoutManager linearLayoutManager) {this.mZoomView =v;

mLinearLayoutManager=linearLayoutManager ;

}

@Overridepublic booleanonTouchEvent(MotionEvent event) {if(mZoomView !=null){if (mZoomViewWidth <= 0 || mZoomViewHeight <= 0) {

mZoomViewWidth=mZoomView.getMeasuredWidth();

mZoomViewHeight=mZoomView.getMeasuredHeight();

}if(mViewParentHeight <= 0) {try{

RelativeLayout parent=(RelativeLayout) mZoomView.getParent();

ViewGroup.LayoutParams layoutParams=parent.getLayoutParams();

mViewParentHeight=layoutParams.height;

}catch(Exception e){}

}//判断触摸事件

switch(event.getAction()) {//触摸结束

caseMotionEvent.ACTION_UP:

mScaling= false;

replyImage();break;//触摸中

caseMotionEvent.ACTION_MOVE://判断是否正在放大 mScaling 的默认值为false

if (!mScaling) {//当图片也就是第一个item完全可见的时候,记录触摸屏幕的位置

if (mLinearLayoutManager.findViewByPosition(mLinearLayoutManager.findFirstVisibleItemPosition()).getTop() == 0) {//记录首次按下位置

mFirstPosition =event.getY();

}else{break;

}

}//滚动距离乘以一个系数

int distance = (int) ((event.getY() - mFirstPosition) *mScrollRate);if (distance < 0) {break;

}//处理放大

mScaling = true;

setZoom(distance);default:break;

}

}return super.onTouchEvent(event);

}private void setZoom(floatdistance) {if (mZoomViewWidth <= 0 || mZoomViewHeight <= 0) {return;

}

ViewGroup.LayoutParams lp=mZoomView.getLayoutParams();

lp.width= (int) (mZoomViewWidth * ((mZoomViewWidth + distance) /mZoomViewWidth));

lp.height= (int) (mZoomViewHeight * ((mZoomViewWidth + distance) /mZoomViewWidth));

mZoomView.setLayoutParams(lp);try{

RelativeLayout parent=(RelativeLayout)mZoomView.getParent();

ViewGroup.LayoutParams layoutParams=parent.getLayoutParams();

layoutParams.height= (int) (mViewParentHeight * ((mZoomViewWidth + distance) /mZoomViewWidth));

parent.setLayoutParams(layoutParams);

}catch(Exception e){

}

}/*** 图片回弹动画*/

private voidreplyImage() {float distance = mZoomView.getMeasuredWidth() -mZoomViewWidth;

ValueAnimator valueAnimator= ValueAnimator.ofFloat(distance, 0f).setDuration((long) (distance *mReplyRate));

valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Overridepublic voidonAnimationUpdate(ValueAnimator animation) {

setZoom((Float) animation.getAnimatedValue());

}

});

valueAnimator.start();

}

布局很简单:

android:id="@+id/rv_personal_info"android:layout_width="match_parent"android:layout_height="wrap_content" />

使用也非常简单了。

实现recylerview的滑动监听,在布局为0的时候,设置图片放大及布局下移操作。

rv_personal_info.addOnScrollListener(object : RecyclerView.OnScrollListener() {

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {this@PersonalInfoActivity.scrollY =recyclerView.computeVerticalScrollOffset()if (scrollY == 0 && pageItems.size != 0) {

rv_personal_info.setZoomView(personalPageHeadViewBinder!!.getZoomView(), rv_personal_info.layoutManager as?LinearLayoutManager)

}

}catch(e:Exception){

e.printStackTrace()

}

}

})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值