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

使用介绍-小实例-自定义一个支持滑动删除事件的控件[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>