• 类似QQ消息左滑删除的Demo


    最近在网上学到一篇类似QQ消息左滑删除的demo,完善了下代码,感觉还不错,特此分享一波:

    CustomSwipeListView.java 是个继承自ListView的类,里面调用了自定义View 类SwipeItemView.java的一个收缩的方法。其实QQ消息删除这个动画可以有很多种方法实现,这里我们介绍的方法是:常规ListView的每个Item展示方式不变,只是在Adapter类里面去绑定该显示的数据和删除等字样。具体详见如下:

    自定义的ListView:

    package com.ryg.slideview;

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.ListView;

    public class CustomSwipeListView extends ListView {

    private static final String TAG = "ListViewCompat";

    public static SwipeItemView mFocusedItemView;

    private int mPosition;

    public CustomSwipeListView(Context context) {
    super(context);
    }

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

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

    public void shrinkListItem(int position) {
    View item = getChildAt(position);

    if (item != null) {
    try {
    ((SwipeItemView) item).shrink();
    }
    catch (ClassCastException e) {
    e.printStackTrace();
    }
    }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
    int x = (int) event.getX();
    int y = (int) event.getY();
    // 我们想知道当前点击了哪一行
    int position = pointToPosition(x, y);
    Log.e(TAG, "postion=" + position);
    if (position != INVALID_POSITION) {
    int firstPos = getFirstVisiblePosition();
    mFocusedItemView = (SwipeItemView) getChildAt(position - firstPos);
    }
    }
    default:
    break;
    }

    if (mFocusedItemView != null) {
    mFocusedItemView.onRequireTouchEvent(event);

    }

    return super.onTouchEvent(event);
    }

    }

    自定义的布局:

    package com.ryg.slideview;

    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.Scroller;
    import android.widget.TextView;

    public class SwipeItemView extends LinearLayout {

    private static final String TAG = "SlideView";

    private Context mContext;

    private LinearLayout mViewContent;

    private RelativeLayout mHolder;

    private Scroller mScroller;

    private OnSlideListener mOnSlideListener;

    private int mHolderWidth;

    private int mLastX = 0;

    private int mLastY = 0;

    private static final int TAN = 2;

    private boolean isHorizontalMove = true;// 判断是否横滑

    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;

    /**
    * @param view
    * current SlideView
    * @param status
    * SLIDE_STATUS_ON or SLIDE_STATUS_OFF
    */
    public void onSlide(View view, int status);
    }

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

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

    private void initView() {
    mContext = getContext();
    // 初始化弹性滑动对象
    mScroller = new Scroller(mContext);
    // 设置其方向为横向
    setOrientation(LinearLayout.HORIZONTAL);
    // 将slide_view_merge加载进来
    View.inflate(mContext, R.layout.slide_view_merge, this);
    mViewContent = (LinearLayout) findViewById(R.id.view_content);

    mHolder = (RelativeLayout) findViewById(R.id.holder);
    mHolder.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    mHolderWidth = mHolder.getMeasuredWidth();
    mHolder.setLayoutParams(new LinearLayout.LayoutParams(mHolderWidth, LayoutParams.MATCH_PARENT));
    }

    public void setButtonText(CharSequence text) {
    ((TextView) findViewById(R.id.delete)).setText(text);
    }

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

    public void setOnSlideListener(OnSlideListener onSlideListener) {
    mOnSlideListener = onSlideListener;
    }

    public void shrink() {
    if (getScrollX() != 0) {
    this.smoothScrollTo(0, 0);
    }
    }

    public void onRequireTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();
    int scrollX = getScrollX();
    Log.d(TAG, "x=" + x + " y=" + y);

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {
    isHorizontalMove = true;// 按下默认为true,当移上下则为false
    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) {
    isHorizontalMove = false;
    break;
    }

    if (!isHorizontalMove)
    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.15 > 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;
    }

    private void smoothScrollTo(int destX, int destY) {
    int scrollX = getScrollX();
    int delta = destX - scrollX;
    mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 2);
    invalidate();
    }

    @Override
    public void computeScroll() {//由父视图调用,用于通知子视图在必要时更新 mScrollX 和 mScrollY 的值。 该操作主要用于子视图使用 Scroller 进行动画滚动时
    if (mScroller.computeScrollOffset()) {
    scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    postInvalidate();
    }
    }

    public boolean getisHorizontalMove() {
    return isHorizontalMove;
    }

    }

    Adapter:

    package com.ryg.slideview;

    import java.util.List;

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.ryg.slideview.SwipeItemView.OnSlideListener;

    public class HistoryListViewAdapter extends BaseAdapter {

    private LayoutInflater mInflater;

    private List<HistoryListItemObject> mMessageItems;

    private Context context;

    private SwipeItemView mLastSlideViewWithStatusOn;

    public HistoryListViewAdapter(Context context, List<HistoryListItemObject> mMessageItems) {
    mInflater = LayoutInflater.from(context);
    this.mMessageItems = mMessageItems;
    this.context = context;
    }

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

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

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

    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    SwipeItemView slideView = (SwipeItemView) convertView;
    if (slideView == null) {
    View itemView = mInflater.inflate(R.layout.history_listview_items, null);
    slideView = new SwipeItemView(context);
    slideView.setContentView(itemView);
    holder = new ViewHolder(slideView);
    slideView.setOnSlideListener(new OnSlideListener() {
    @Override
    public void onSlide(View view, int status) {
    // TODO Auto-generated method stub
    if (mLastSlideViewWithStatusOn != null && mLastSlideViewWithStatusOn != view) {
    mLastSlideViewWithStatusOn.shrink();
    }
    if (status == SLIDE_STATUS_ON) {
    mLastSlideViewWithStatusOn = (SwipeItemView) view;
    }
    }
    });
    slideView.setTag(holder);
    }
    else {
    holder = (ViewHolder) slideView.getTag();
    }
    HistoryListItemObject item = mMessageItems.get(position);
    if (CustomSwipeListView.mFocusedItemView != null) {
    CustomSwipeListView.mFocusedItemView.shrink();
    }

    holder.icon.setImageResource(item.getIconRes());
    holder.title.setText(item.getTitle());
    holder.msg.setText(item.getMsg());
    holder.deleteHolder.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View arg0) {
    mMessageItems.remove(position);
    Toast.makeText(context, String.valueOf(position), Toast.LENGTH_SHORT).show();
    notifyDataSetChanged();
    }
    });

    return slideView;
    }

    private static class ViewHolder {
    public ImageView icon;

    public TextView title;

    public TextView msg;

    public ViewGroup deleteHolder;

    ViewHolder(View view) {
    icon = (ImageView) view.findViewById(R.id.icon);
    title = (TextView) view.findViewById(R.id.title);
    msg = (TextView) view.findViewById(R.id.msg);
    deleteHolder = (ViewGroup) view.findViewById(R.id.holder);
    }
    }
    }

    布局:

    没有删除布局的Item布局:

    <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="wrap_content"
    android:descendantFocusability="blocksDescendants"
    android:gravity="center_vertical"
    android:paddingBottom="5dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="5dp" >

    <ImageView
    android:id="@+id/icon"
    android:layout_width="160dp"
    android:layout_height="50dp"
    android:layout_marginRight="5dp"
    android:scaleType="fitStart"
    android:src="@drawable/wechat_icon" />

    <TextView
    android:id="@+id/title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/icon"
    android:gravity="right"
    android:hint="title"
    android:textColor="@color/black"
    android:textSize="15sp" />

    <TextView
    android:id="@+id/msg"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@id/icon"
    android:layout_alignLeft="@id/title"
    android:gravity="right"
    android:hint="message"
    android:textColor="@color/grey" />


    </RelativeLayout>

    Merge成最终的Item的布局:

    <?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="match_parent"
    android:orientation="horizontal" >
    </LinearLayout>

    <RelativeLayout
    android:id="@+id/holder"
    android:layout_width="120dp"
    android:layout_height="match_parent"
    android:background="#5FBBB9"
    android:clickable="true" >

    <TextView
    android:id="@+id/delete"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:text="解绑"
    android:textColor="@color/floralwhite" />

    </RelativeLayout>

    </merge>

    最后在Activity里面去用CustomSwipeListView这个自定义View就好了,因为它继承自ListView,所以直接用Adapter绑定数据.

  • 相关阅读:
    Hibernate中的HQL
    hibernate配置数据库连接池三种用法
    Hibernate的延迟检索和立即检索
    Hibernate关系映射中的注解
    Hibernate的多种关系映射(oto、otm、mtm)
    自然主键和代理主键的区别
    Hibernate的xml方法配置和操作代码
    Hibernate简介
    VirtualBox从USB设备(PE)启动图文教程
    属性动画
  • 原文地址:https://www.cnblogs.com/yuanting/p/5130977.html
Copyright © 2020-2023  润新知