您的位置:首页 > 移动开发 > Android开发

Android Scroller详解,实现仿QQ列表item侧滑删除功能

2016-11-22 17:30 811 查看

概述

Scroller,主要用于实现View的滚动。这个滚动主要是指平滑滚动

要想通过Scroller实现滑动,只要实现以下步骤即可:

创建一个Scroller对象,调用startScroll方法,然后调用invalidate()方法重新绘制View

重写View的computeScroll方法

在computeScroll方法中,调用Scroller的computeScrollOffset方法,该方法用于判断滑动是否结束

如果滑动没有结束,通过调用scrollTo方法和postInvalidate方法完成滑动

简单代码实现如下:

//1、启动滑动
public void scroll(){
Scroller.startScroll(getScrollX(), getScrollY(), offsetX, offsetY);
invalidate();
}

//实现具体的滑动逻辑
public void computeScroll() {
super.computeScroll();

if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}


scrollTo和scrollBy介绍

在Android的View类中,已经为大家提供了scrollTo和scrollBy方法实现View的滑动。

scrollTo和scrollBy方法的区别:

scrollTo:绝对位置滑动,即相对View的初始位置滑动。

scrollBy:相对位置滑动,即相对View的当前位置滑动。

通过查看源码可知,scrollBy方法的内部也是通过调用scrollTo方法实现的:

public void scrollTo(int x, int y) {
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}

public void scrollBy(int x, int y) {
//其中mScrollX、和mScrollY表示相对初始位置的滑动距离
// x、y表示滑动偏移量
scrollTo(mScrollX + x, mScrollY + y);
}


这里有一点需要注意scrollTo和scrollBy方法中的参数:向右滑动参数为负值,向左滑动参数为正值

实现QQ侧滑控件

代码如下:

package com.zhangke.a07_02_scrollerdemo1;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.Scroller;

/**
* 仿QQ item侧滑删除按钮
*/
public class SlidingLinearLayout extends LinearLayout {

private View leftView;
private View rightView;

private Scroller mScroller;
private int mTouchSlop;
private float startX;
private float startY;
private float distX;
private float distY;

public SlidingLinearLayout(Context context) {
this(context, null);
}

public SlidingLinearLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public SlidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

//创建一个Scroller对象
mScroller = new Scroller(getContext());
//表示系统指定的滑动的最小距离
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
//正常显示的view
leftView = getChildAt(0);
//通过滑动显示的view
rightView = getChildAt(1);
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();

super.dispatchTouchEvent(event);
return true;

case MotionEvent.ACTION_MOVE:
distX = event.getX() - startX;
distY = event.getY() - startY;
//判断是否是左右滑动
if (Math.abs(distX) - Math.abs(distY) > mTouchSlop) {

//判断滑动的边界:0 ~ rightView.getWidth()
//因为View是向左滑动的,那么View的偏移量是大于0的,那么通过getScrollX的值大于0,通过(-distX)也是大于0的

float offsetX = getScrollX() + (-distX);
if (offsetX > rightView.getWidth() || offsetX < 0) {
return true;
}

//向左滑动,参数为正
scrollBy((int) -distX, 0);

startX = event.getX();
startY = event.getY();
return true;
}

break;
case MotionEvent.ACTION_UP:
//当松开手指时、判断滑动是否大于rightView的一半,如果大于那么完全显示rightView,否则隐藏rightView
//计算偏移量
int offset = getScrollX() / (float) rightView.getWidth() > 0.5f ? rightView.getWidth() - getScrollX() : -getScrollX();

//实现滑动
mScroller.startScroll(getScrollX(), getScrollY(), offset, 0);
invalidate();
startX = 0;
startY = 0;
distX = 0;
distY = 0;

break;
}

return super.onTouchEvent(event);
}

@Override
public void computeScroll() {
super.computeScroll();

//判断滑动是否结束
if (mScroller.computeScrollOffset()) {
//通过scrollTo方法滑动
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
}


在项目中使用

activity代码:

package com.zhangke.a07_02_scrollerdemo1;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private List<String> datas;
private ListView listView;

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

listView = (ListView) findViewById(R.id.listview);

datas = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
datas.add("item " + i);
}

listView.setAdapter(new MyAdapter());
}

class MyAdapter extends BaseAdapter {

@Override
public int getCount() {
return datas.size();
}

@Override
public Object getItem(int position) {
return datas.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(MainActivity.this, R.layout.item, null);
}

TextView textview = (TextView) convertView.findViewById(R.id.textview);
textview.setText(datas.get(position));

return convertView;
}
}
}


item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.zhangke.a07_02_scrollerdemo1.SlidingLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorAccent"
android:orientation="horizontal">

<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="正常显示的view" />

<LinearLayout
android:layout_width="100dp"
android:layout_height="50dp"
android:background="@color/colorPrimaryDark"
android:orientation="horizontal">

<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:background="#8bc662"
android:text="置顶" />

<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#5694ff"
android:gravity="center"
android:text="删除" />

</LinearLayout>

</com.zhangke.a07_02_scrollerdemo1.SlidingLinearLayout>


效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: