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
<?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]如需要转载,请注明出处,谢谢!!