Android学习之 Scroller的介绍与使用

  • 类概述

    Android里Scroller类是为了实现View平滑滚动的一个Helper类。通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context)设置mScroller滚动的位置时,并不会导致View的滚动通常是用mScroller*记录/计算View滚动的位置*,再重写View的computeScroll(),调用View的scrollTo(int x,int y)方法完成实际的滚动

  • 主要方法介绍

    技术分享

更多关于Scroller类API详细介绍可前往
http://api.apkbus.com/reference/android/widget/Scroller.html

  • 使用介绍-小实例-自定义一个支持滑动删除事件的控件[SlideView]

    • 首先看一下实例的效果演示:
      技术分享

    • 下面是实现代码

      • 自定义控件布局文件:slide_view.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/view_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

    </LinearLayout>

    <LinearLayout
        android:id="@+id/holder"
        android:layout_width="80dp"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:orientation="horizontal"
        android:background="@android:color/darker_gray">

        <TextView
            android:id="@+id/delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:textColor="@android:color/white"
            android:text="detele"/>

    </LinearLayout>

</merge>
 - 自定义控件实现类:SlideView.java [内含Scroller的使用介绍]
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

/**
 * Created by ice on 15/5/4.
 */
public class SlideView extends LinearLayout{

    private Context mContext;

    private LinearLayout mViewContent;

    private LinearLayout mHolder;

    private TextView tv_delete;

    // 弹性滑动对象,实现View平滑滚动的一个帮助类
    private Scroller mScroller;

    // 滑动回调接口,用来向上层通知滑动事件
    private OnSlideListener mOnSlideListener;

    private int mHolderWidth = 100;

    private int mLastX = 0;

    private int mLastY = 0;

    private static final int TAN = 2;


    public SlideView(Context context) {
        super(context);
        initView();
    }

    public SlideView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }


    private void initView(){
        mContext = getContext();
        mScroller = new Scroller(mContext);
        setOrientation(LinearLayout.HORIZONTAL);
        setGravity(Gravity.CENTER_VERTICAL);

        View.inflate(mContext, R.layout.slide_view, this);
        mViewContent = (LinearLayout)findViewById(R.id.view_content);
        mHolder = (LinearLayout)findViewById(R.id.holder);

        tv_delete = (TextView)findViewById(R.id.delete);

    }


    public void setButtonText(CharSequence text){
        tv_delete.setText(text);
    }


    public void setContentView(View view){
        mViewContent.addView(view);
    }


    public void onRequireTouchEvent(MotionEvent event){
            int x = (int)event.getX();
            int y = (int)event.getY();
            int scrollX = getScrollX();
            switch (event.getAction()){
                case MotionEvent.ACTION_DOWN:
                    if(!mScroller.isFinished()){
                        mScroller.abortAnimation();
                    }
                    if(mOnSlideListener != null){
                        mOnSlideListener.onSlide(this, OnSlideListener.SLIDE_STATUS_START_SCROLL);
                    }

                    break;

                case MotionEvent.ACTION_MOVE:
                    int deltaX = x - mLastX;
                    int deltaY = y - mLastY;
                    if(Math.abs(deltaX) < Math.abs(deltaY)*TAN){
                        // 滑动不满足条件 不做横向滑动
                        break;
                    }

                    int newScrollX = scrollX - deltaX;
                    if(deltaX != 0){
                        if(newScrollX < 0){
                            newScrollX = 0;
                        }else if(newScrollX > mHolderWidth){
                            newScrollX = mHolderWidth;
                        }
                        this.scrollTo(newScrollX, 0);
                    }

                    break;

                case MotionEvent.ACTION_UP:
                    int newScrollx = 0;
                    if(scrollX - mHolderWidth*0.75 > 0){
                        newScrollx = mHolderWidth;
                    }

                    this.smoothScrollTo(newScrollx, 0);
                    // 通知上层滑动事件
                    if(mOnSlideListener != null){
                        mOnSlideListener.onSlide(this, newScrollx == 0 ? OnSlideListener.SLIDE_STATUS_OFF
                                : OnSlideListener.SLIDE_STATUS_ON);
                    }

                    break;

                default:
                    break;
            }

            mLastX = x;
            mLastY = y;
    }


    /**
     * 调用此方法滚动到目标位置
     * @param fx  目标x坐标
     * @param fy  目标Y坐标
     */
    private void smoothScrollTo(int fx, int fy){
        int scrollX = getScrollX();
        int dx = fx - scrollX;

        int scrollY = getScrollY();
        int dy = fy - scrollY;
        //设置mScroller的滚动偏移量
        mScroller.startScroll(scrollX, scrollY, dx, dy, Math.abs((dx)*3));

        invalidate();
    }


    /**
     * 由mScroller记录/计算好View滚动的位置后,最后由View的computeScroll(),完成实际的滚动
     */
    @Override
    public void computeScroll() {
        //先判断mScroller滚动是否完成
        if(mScroller.computeScrollOffset()){
            //这里调用View的scrollTo()完成实际的滚动
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            //必须调用该方法,否则不一定能看到滚动效果
            postInvalidate();
        }
        super.computeScroll();
    }


    /**
     * 设置滑动回调
     * @param onSlideListener
     */
    public void setOnSlideListener(OnSlideListener onSlideListener){
        this.mOnSlideListener = onSlideListener;
    }


    public interface OnSlideListener {
        public static final int SLIDE_STATUS_OFF = 0;
        public static final int SLIDE_STATUS_START_SCROLL = 1;
        public static final int SLIDE_STATUS_ON = 2;

        public void onSlide(View view, int status);
    }

}
 - Activity布局文件:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_content"
        android:text="向左滑动控件删除"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <demo.ice.com.helloapple.SlideView
        android:id="@+id/sv_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_content" >

    </demo.ice.com.helloapple.SlideView>

</RelativeLayout>
 - Activity类:MainActivity.java
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity implements SlideView.OnSlideListener, View.OnClickListener{

    private SlideView slideView;

    private LinearLayout slide_delete;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        slideView = (SlideView)findViewById(R.id.sv_view);

        View slideContentView = View.inflate(MainActivity.this, R.layout.slide_list_item, null);
        slideView.setContentView(slideContentView);
        slideView.setButtonText("删除");

        slide_delete = (LinearLayout)findViewById(R.id.holder);

        slideView.setOnSlideListener(this);
        slide_delete.setOnClickListener(this);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 将事件交由slideView自身处理
        slideView.onRequireTouchEvent(event);
        return super.onTouchEvent(event);
    }

    @Override
    public void onClick(View view) {
        if(view.getId() == R.id.holder){
             Toast.makeText(MainActivity.this, "你点击了删除按钮", Toast.LENGTH_LONG).show();
        }

    }

    @Override
    public void onSlide(View view, int status) {

    }
}
 - 填充自定义控件内容布局文件:slide_list_item.xml     
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_menu_camera"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="13岁iOS开发者:Swift开发Sprite Kit游戏实践"/>

</LinearLayout>




如果您对文章内容有任何疑问或有更好的见解, 欢迎通过留言或发邮件的方式联系我:
[email protected]

如需要转载,请注明出处,谢谢!!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。