【Android】一个适用于大图界面向下拖拽返回的效果

GitHub:DragBottom

适用于查看大图的下拉拖拽返回控件
共享元素适用于5.0+




最初看到这个效果是在IOS系统的短信App,后来在IOS微信、腾讯新闻中都发现了类似的效果。

网络上好像也没有类似的代码,所以决定自己动手写一个。

一想到拖拽,首先会想到ViewDragHelper,关于这个类的使用方法可以参考

http://blog.csdn.net/lmj623565791/article/details/46858663

Hongyang的博客解析

需求分析:在使用微信、腾讯新闻中该效果只允许向往下拖拽一定距离后处于触摸状态时便可全屏拖拽。并且向上向下拖拽时,会对视图的背景透明度、大小有一定变化,越往下越透明,可见上级界面。

当往下拖动一定距离松手时,触发返回上级界面。反之距离不够,视图将返回原先位置。


1、创建ViewDragHelper

mDragHelper=ViewDragHelper.create(this,1.0f,new ViewDragHelper.Callback(){
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                //允许子视图进行拖拽,这里默认都允许
                return true;
            }
        });
2、设定拖拽边界以及方向,只允许向下

@Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                //不允许向上拖动,取值top表示允许上下拖拽-1920~1920
                //这里设置假设top<0时,直接设定为0,即不允许向上拖拽
                return Math.max(top,0);
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                //0不允许水平拖拽,取值left表示允许左右拖拽left=-1080~1080
                return 0;
            }
3、如此就能设定向下拖拽了,接下来往下拖动一定距离时,释放限制,这里设定为100px,代码改造后如下
/**是否允许所有方向拖拽*/
            boolean needDrag;
            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                if (needDrag) {
                    return top;
                }
                if (top < 0) {//只允许向下拖拽
                    top = 0;
                } else if (top > 100) {//向下拖拽超过100px后,释放允许任何方向拖拽
                    needDrag = true;
                }
                return top;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                return needDrag ? left : 0;
            }
4、 向下拖拽时要有缩放的一个效果,我们需要重写另一个函数

/**
             *
             * @param changedView   被拖动的View
             * @param left          水平拖动距离
             * @param top           垂直拖动距离
             * @param dx            每次拖拽产生的水平距离x2-x1
             * @param dy            每次拖拽产生的垂直距离y2-y1
             */
            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
            }

4.1、为了计算出实时的拖动百分比

直接用top除以view的高度即可:

向下拖动100px后公示为:1-100/1920=0.95、

向下拖动300px后公示为:1-300/1920=0.85。

即:View从原始尺寸渐渐缩小,这里我们给定最小缩放倍率0.5f,最大1.0f。当然这个倍率也可以随时调整

@Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                float present = 1 - (top * 1.0f) / (getHeight());

                float maxScale = Math.min(present, 1.0f);//Max,1.0f
                float minScale = Math.max(0.5f, maxScale);//Min,5.0f;

                changedView.setScaleX(minScale);
                changedView.setScaleY(minScale);
            }
5、接下来是背景透明度的变换,要达到的效果是能看到上一级Activity的界面。

所以首页要将当期的Activity的主题样式设置成透明化

<style name="AppTheme.drag">
        <item name="android:windowIsTranslucent">true</item>
</style>
应用

<activity android:name=".DragActivity"
          android:theme="@style/AppTheme.drag"/>
5.1、背景透明度的变化第一时间想到的就是View的背景颜色

了解过Activity布局层级的都知道顶层布局是DecorView

所以我们首先给DecorView设置为纯黑色,然后拖动时修改其背景颜色即可

在布局中取得DecorView:

if (getContext() instanceof Activity) {
            ((Activity) getContext()).getWindow().getDecorView().setBackgroundColor(DEF_BG_COLOR);
        }
和View缩放相同的道理,实时获取百分比即可,最大不超过255

/**
             *
             * @param changedView   被拖动的View
             * @param left          水平拖动距离
             * @param top           垂直拖动距离
             * @param dx            每次拖拽产生的水平距离x2-x1
             * @param dy            每次拖拽产生的垂直距离y2-y1
             */
            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                float present = 1 - (top * 1.0f) / (getHeight());

                if (getContext() instanceof Activity) {
                    int alpah = Math.min((int) (255 * present), 255);
                    ((Activity) getContext()).getWindow().getDecorView().setBackgroundColor(Color.argb(alpah, 0, 0, 0));
                }

                float maxScale = Math.min(present, 1.0f);//Max,1.0f
                float minScale = Math.max(0.5f, maxScale);//Min,5.0f;

                changedView.setScaleX(minScale);
                changedView.setScaleY(minScale);
            }

6接下来最后一个步骤要设定一个拖动触发关闭的界限,这里取了View拖动的1/4距离长度,当然可以随意修改。

超过设定距离,触发关闭

反之,将View归位

定义变量

boolean mNeedRelease;
@Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);

                mNeedRelease = top > getHeight() * 0.25;//Release
重写释放拖拽的函数,触发onBackPressed方法finish掉当前Activity
boolean mNeedRelease;
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                super.onViewReleased(releasedChild, xvel, yvel);

                if (mNeedRelease) {
                    if (getContext() instanceof Activity) {
                        ((Activity) getContext()).onBackPressed();
                    }
                } else {
                    needDrag = false;
                    //让视图归位
                    mDragHelper.settleCapturedViewAt(finalLeft, finalTop);
                    releasedChild.setScaleX(1.0f);
                    releasedChild.setScaleY(1.0f);
                    invalidate();
                }
            }











  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现Android 界面中任意拖动图片的功能,可以使用 onTouchEvent() 方法来实现。以下是一个简单的代码示例: 首先,在 layout.xml 文件中添加一个 ImageView: ```xml <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/my_image" /> ``` 然后,在 Activity 中添加以下代码: ```java public class MainActivity extends AppCompatActivity { private ImageView imageView; private float startX, startY; private int lastAction; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.imageView); imageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: startX = imageView.getX() - event.getRawX(); startY = imageView.getY() - event.getRawY(); lastAction = MotionEvent.ACTION_DOWN; break; case MotionEvent.ACTION_MOVE: imageView.setX(event.getRawX() + startX); imageView.setY(event.getRawY() + startY); lastAction = MotionEvent.ACTION_MOVE; break; case MotionEvent.ACTION_UP: if (lastAction == MotionEvent.ACTION_DOWN) Toast.makeText(MainActivity.this, "Clicked!", Toast.LENGTH_SHORT).show(); break; default: return false; } return true; } }); } } ``` 在代码中,我们使用了 setOnTouchListener() 方法来监听 ImageView 的触摸事件。在触摸事件中,我们使用了 switch-case 语句来处理不同的事件类型。在 ACTION_DOWN 事件中,我们记录了起始的触摸点位置,并设置 lastAction 变量为 ACTION_DOWN。在 ACTION_MOVE 事件中,我们计算了手指移动的距离,并将 ImageView 的位置设置为手指的当前位置加上起始的偏移量。在 ACTION_UP 事件中,我们检查 lastAction 变量是否为 ACTION_DOWN,如果是,就认为用户单击了 ImageView。 这样,就可以实现Android 界面中任意拖动图片的功能了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值