Android scroll应用--仿高铁管家订单下拉与上拉

本文介绍了一种自定义的滑动广告幕布组件CurtainView2的实现细节,包括如何通过触摸操作实现广告幕布的展开与收起,并使用了BounceInterpolator为动画效果增加反弹感。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.example.customslidemenu.scrolltest;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Scroller;

import com.example.customslidemenu.R;
import com.example.customslidemenu.window.BaseTools;
import com.example.customslidemenu.window.CurtainView;

/**
 * Created by Administrator on 2017/1/9.
 */
public class CurtainView2 extends RelativeLayout implements View.OnTouchListener {

    private static String TAG = "CurtainView";
    private Context mContext;
    /** Scroller 拖动类 */
    private Scroller mScroller;
    /** 屏幕高度  */
    private int mScreenHeigh = 0;
    /** 屏幕宽度  */
    private int mScreenWidth = 0;
    /** 点击时候Y的坐标*/
    private int downY = 0;
    /** 拖动时候Y的坐标*/
    private int moveY = 0;
    /** 拖动时候Y的方向距离*/
    private int scrollY = 0;
    /** 松开时候Y的坐标*/
    private int upY = 0;
    /** 广告幕布的高度*/
    private int curtainHeigh = 0;
    /** 是否 打开*/
    private boolean isOpen = false;
    /** 是否在动画 */
    private boolean isMove = false;
    /** 绳子的图片*/
    private ImageView img_curtain_rope;
    /** 广告的图片*/
    private ImageView img_curtain_ad;
    /** 上升动画时间 */
    private int upDuration = 1000;
    /** 下落动画时间 */
    private int downDuration = 500;

    public CurtainView2(Context context) {
        super(context);
        init(context);
    }

    public CurtainView2(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public CurtainView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    /** 初始化 */
    private void init(Context context) {
        this.mContext = context;
        //Interpolator 设置为有反弹效果的  (Bounce:反弹)
        Interpolator interpolator = new BounceInterpolator();
        mScroller = new Scroller(context, interpolator);

        mScreenHeigh = BaseTools.getWindowHeigh(context);
        mScreenWidth = BaseTools.getWindowWidth(context);
        // 背景设置成透明
        this.setBackgroundColor(Color.argb(0, 0, 0, 0));
        final View view = LayoutInflater.from(mContext).inflate(R.layout.curtain_layout2, null);

        img_curtain_ad = (ImageView)view.findViewById(R.id.img_curtain_ad);
        img_curtain_rope = (ImageView)view.findViewById(R.id.img_curtain_rope);

        addView(view);
        img_curtain_ad.post(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                curtainHeigh  = img_curtain_ad.getHeight();

                CurtainView2.this.scrollTo(0, -curtainHeigh);  //开始时,将广告面板隐藏起来,身体下滑动广告高度
                System.out.println("93------------mScreenHeigh:" + mScreenHeigh);
                System.out.println("94------------curtainHeigh: " + curtainHeigh);
                System.out.println("95------------getScrollY(): " + getScrollY());

            }
        });
        img_curtain_rope.setOnTouchListener(this);
    }

    /**
     * 拖动动画
     * @param startY
     * @param dy  垂直距离, 滚动的y距离
     * @param duration 时间
     */
    public void startMoveAnim(int startY, int dy, int duration) {
        isMove = true;
        mScroller.startScroll(0, startY, 0, dy, duration);
        invalidate();//通知UI线程的更新
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        super.onLayout(changed, l, t, r, b);
    }

    @Override
    public void computeScroll() {
        //判断是否还在滚动,还在滚动为true
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            //更新界面
            postInvalidate();
            isMove = true;
        } else {
            isMove = false;
        }
        super.computeScroll();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        if (!isMove) {
            int offViewY = 0;//屏幕顶部和该布局顶部的距离
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downY = (int) event.getRawY();
                    offViewY = downY - (int)event.getY();
                    return true;
                case MotionEvent.ACTION_MOVE:
                    moveY = (int) event.getRawY();
                    scrollY = moveY - downY;

                    if (scrollY > 0) {  // 手指向下滑动
                        if(isOpen){

                            if(scrollY <= curtainHeigh){
                                System.out.println("145-----------------down:"+scrollY+":isOpen:"+isOpen);
                                scrollTo(0,  -scrollY);
                            }
                        }

                    } else {    // 手指向上滑动,此时判断页面是否已经打开,如果没有打开 应该打开页面,同时需要判断极值点
                        if(!isOpen){

                            if(Math.abs(scrollY) <= curtainHeigh){
                                System.out.println("159------------"+(- curtainHeigh - scrollY));
                                scrollTo(0, - curtainHeigh - scrollY);
                            }
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    upY = (int) event.getRawY();
                    if(Math.abs(upY - downY) < 10){
                        onRopeClick();
                        break;
                    }
                    if (downY > upY) {  // 向上滑动
                        if (Math.abs(scrollY) > curtainHeigh / 2) {// 向上滑动超过半个屏幕高的时候 打开
                            startMoveAnim(0, 0,upDuration);
                            isOpen = true;
                        } else {        //否则,关闭
                            //startMoveAnim(0, -curtainHeigh,upDuration);
                            System.out.println("181------------:"+this.getScrollY());
                            startMoveAnim(this.getScrollY(), (-curtainHeigh - this.getScrollY()),upDuration);

                            isOpen = false;
                        }
                    } else {            // 向下滑动

                        if (scrollY < curtainHeigh / 2) {  //  向上打开视图
                            System.out.println("184---------------down_open");
                            //startMoveAnim(this.getScrollY(), -this.getScrollY(),upDuration);
                            startMoveAnim(0, 0,upDuration);
                            isOpen = true;
                        } else {        //向下滑动超过半个屏幕高的时候,向下关闭视图
                            System.out.println("184---------------down_close");
                            startMoveAnim(this.getScrollY(),(-curtainHeigh - this.getScrollY()), upDuration);
                            //startMoveAnim(0, -curtainHeigh,upDuration);
                            isOpen = false;
                        }
                    }
                    break;
                default:
                    break;
            }
        }
        return false;
    }
    /**
     * 点击绳索开关,会展开/关闭
     * onToch中使用这个中的方法来当点击事件,避免了点击时候响应onTouch的衔接不完美的影响
     */
    public void onRopeClick(){
        if(isOpen){
            CurtainView2.this.startMoveAnim(0, -curtainHeigh, upDuration);  //关闭
        }else{
            CurtainView2.this.startMoveAnim(0,0, upDuration);  //打开
        }
        isOpen = !isOpen;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值