实现一个简单的页面下拉/上拉效果

这是未下拉的样子:

在这里插入图片描述

这是下拉的样子

在这里插入图片描述

代码实现


public class Sliding extends AppCompatActivity  {

    private ConstraintLayout topView;
    private ImageView touchImg;
    private int mMeasuredHeight;
    private int downY;
    private boolean mIsDown;
    private VelocityTracker mVelocityTracker;
    private static final float MINPERCENT = 0.1f;
    private static final float MAXPERCENT = 0.9f;
    private Handler mHandler = new Handler();
    private int mScreenHeight;
    private ViewGroup.LayoutParams mLayoutParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sliding);
        initView();
        initTouchEvent();
    }

    private void initView() {
        topView = findViewById(R.id.top_view);
        touchImg = findViewById(R.id.touch_img);
        mScreenHeight = measureScreenHeight();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initTouchEvent() {
        mLayoutParams = topView.getLayoutParams();
        touchImg.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                addVelocityTracker(event);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:// 获取手指第一次接触屏幕
                        //获取第一次触摸手指坐标
                        downY = (int) event.getRawY();
                        mMeasuredHeight = topView.getMeasuredHeight();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int moveY = (int) event.getRawY();
                        int changeY = moveY - downY;
                        if (changeY > 0) {
                            mIsDown = true;
                        } else {
                            mIsDown = false;
                        }
                        mMeasuredHeight = mMeasuredHeight + changeY;
                        if (mMeasuredHeight >= 120 &&
                            mMeasuredHeight <= mScreenHeight - topView.getY()) {
                            mLayoutParams.height = mMeasuredHeight;
                            topView.setLayoutParams(mLayoutParams);
                        }
                        downY = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_UP:
                        if (mIsDown) {
                            boolean isShow = (mMeasuredHeight - topView.getY()) / (mScreenHeight - topView.getY()) >= MINPERCENT;
                            smoothSlide(isShow, mMeasuredHeight);
                        } else {
                            boolean isShow = (mMeasuredHeight - topView.getY()) / (mScreenHeight - topView.getY()) >= MAXPERCENT;
                            smoothSlide(isShow, mMeasuredHeight);
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    private void smoothSlide(final boolean isShow, final int startY) {
        final int timeUnit = 5;
        float minValue = 22;
        final int speedY = getVelocity(timeUnit, minValue);

        mHandler.post(new Runnable() {
            int y = startY;
            int speed = speedY;

            @Override
            public void run() {
                if (isShow) {
                    y += speed;
                } else {
                    y -= speed;
                }
                speed += 5;

                boolean finish = false;

                if (isShow) {
                    if (y <= mScreenHeight - topView.getY()) {
                        mLayoutParams.height = y;
                        topView.setLayoutParams(mLayoutParams);
                    } else {
                        mLayoutParams.height = (int) (mScreenHeight - topView.getY());
                        topView.setLayoutParams(mLayoutParams);
                        finish = true;
                    }
                } else {
                    if (y >= 120) {
                        mLayoutParams.height = y;
                        topView.setLayoutParams(mLayoutParams);
                    } else {
                        mLayoutParams.height = 120;
                        topView.setLayoutParams(mLayoutParams);
                        finish = true;
                    }
                }

                if (!finish) {
                    mHandler.post(this);
                }
            }
        });

    }

    private void addVelocityTracker(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        } else {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mVelocityTracker.clear();
            }
        }
        mVelocityTracker.addMovement(event);
    }

    private int getVelocity(int timeUnit, float minValue) {
        if (mVelocityTracker == null) {
            return 0;
        }
        mVelocityTracker.computeCurrentVelocity(timeUnit);
        float speed = Math.abs(mVelocityTracker.getYVelocity());
        return (int) (speed <= minValue ? minValue : speed);
    }

    /**
     * 获取屏幕的高
     */
    private int measureScreenHeight() {
        Point point = new Point();
        WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getSize(point);
        return point.y;
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/content_bg"
    android:orientation="vertical"
    tools:context=".Activity.Sliding">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/top_view"
        android:layout_width="1000px"
        android:layout_height="140px"
        android:layout_gravity="center"
        android:layout_marginTop="200px"
        android:background="@drawable/updating_bg_def"
        android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="100px"
            android:layout_marginTop="10px"
            app:layout_constraintTop_toTopOf="parent">

        </RelativeLayout>

        <ImageView
            android:id="@+id/touch_img"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20px"
            android:src="@drawable/slide_down"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary">


    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值