• 自己实现一个右滑删除的ListView


    参考了以下源码:https://github.com/baoyongzhang/SwipeMenuListView

    实现的效果(顺便推荐一个视频转gif的网址:http://www.gif5.net/)

    首先抛出几个问题:

    1.如何根据我们的手势判定要左滑的position

    2.滑动到什么程度让左滑的Menu显示出来

    3.怎么处理item左滑与ListView的滑动的冲突

    4.menu怎么添加

    5.只能有一个是Open的状态,如果Item1是Open,这时候点击或者滑动Item2,应该使Item1关闭(拦截触摸事件,稍候详细添加)

    首先,定义一个CustomSlideDeleteItemView,这个View的layout要重写,确定menu的摆放位置,具体见代码

    package com.example.myapp.view;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.FrameLayout;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import com.example.myapp.R;
    import com.example.myapp.util.Methods;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by zyr
     * DATE: 16-3-19
     * Time: 下午3:54
     * Email: yanru.zhang@renren-inc.com
     */
    public class CustomSlideDeleteItemView extends FrameLayout{
        private Context mContext;
        private List<View> menuViews = new ArrayList<>();
        private View contentView;
        private LinearLayout menuViewContainer;
        private int contentViewId;
        private int contentViewWidth,contentViewHeight,menuWidth,menuHeight;
    
        public boolean isMenuOpen() {
            return isMenuOpen;
        }
    
        private boolean isMenuOpen = false;
    
        public void setOnMenuClickListener(OnMenuClickListener onMenuClickListener) {
            this.onMenuClickListener = onMenuClickListener;
        }
        private OnMenuClickListener onMenuClickListener;
    
        public interface OnMenuClickListener{
            void onMenuClick(int i,int counts);
        }
        public CustomSlideDeleteItemView(Context context) {
            this(context, null);
        }
    
        public CustomSlideDeleteItemView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CustomSlideDeleteItemView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            menuWidth = Methods.computePixelsWithDensity(mContext,100);
            Log.d("zyr","menuWidth:" + menuWidth);
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomSlideDeleteItemView);
            for(int i=0;i<typedArray.length();i++){
                int attr = typedArray.getIndex(i);
                switch (attr){
                    case R.styleable.CustomSlideDeleteItemView_contentViewId:
                        contentViewId = typedArray.getResourceId(R.styleable.CustomSlideDeleteItemView_contentViewId,0);
                        break;
                }
            }
            if(contentViewId!=0){
                contentView = findViewById(contentViewId);
            }
            menuViewContainer = new LinearLayout(mContext);
            menuViewContainer.setOrientation(LinearLayout.HORIZONTAL);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
            addView(menuViewContainer, layoutParams);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            if(contentView!=null){
                contentView.layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
            }
            layoutMenu();
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            if(w!=oldw || h!=oldh){
                contentViewHeight = menuHeight = h;
                contentViewWidth = w;
    //            Log.d("zyr","contentViewWidth:" + contentViewWidth);
            }
        }
    
        public void addMenu(String s,int color){
            TextView textView = new TextView(mContext);
            textView.setText(s);
            textView.setBackgroundColor(color);
            textView.setTextColor(getResources().getColor(R.color.white));
            textView.setGravity(Gravity.CENTER);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(menuWidth, ViewGroup.LayoutParams.MATCH_PARENT);
            menuViews.add(textView);
            menuViewContainer.addView(textView, layoutParams);
            invalidate();
            for(int i=0;i<menuViews.size();i++){
                final int position = i;
                View view = menuViews.get(i);
                view.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(onMenuClickListener!=null){
                            onMenuClickListener.onMenuClick(position,menuViews.size());
                            scrollBack();
                        }
                    }
                });
            }
        }
    
        public void clearAllMenu(){
            menuViews.clear();
            menuViewContainer.removeAllViews();
            invalidate();
        }
    
        private void layoutMenu() {
            menuViewContainer.layout(contentViewWidth, 0, contentViewWidth + menuWidth * menuViews.size(), contentViewHeight);
        }
    
        public void scroll(int deltaX,int lastDeltaX) {
            if(deltaX < 0){
                Log.d("zyr","deltaX:" + deltaX);
                Log.e("zyr","menuWidth * menuViews.size():" + menuWidth * menuViews.size());
    
                if(Math.abs(deltaX) > menuWidth * menuViews.size() ){
                    scrollTo(menuWidth * menuViews.size(), 0);
                    isMenuOpen = true;
                }else{
                    scrollBy(-lastDeltaX, 0);
                }
            }else{
                if(isMenuOpen()){
                    Log.d("zyr","deltaX:" + deltaX);
                    Log.e("zyr", "menuWidth * menuViews.size():" + menuWidth * menuViews.size());
    
                    if(Math.abs(deltaX) > menuWidth * menuViews.size()){
                        scrollTo(0,0);
                        isMenuOpen = false;
                    }else{
                        scrollBy(-lastDeltaX, 0);
                    }
                }
            }
        }
    
        public void autoScroll(int deltaX){
            if(deltaX < 0){
                if(Math.abs(deltaX) < menuWidth){
                    scrollTo(0, 0);
                    isMenuOpen = false;
                }else{
                    scrollTo(menuWidth * menuViews.size(), 0);
                    isMenuOpen = true;
                }
            }else{
                if(isMenuOpen()){
                    if(Math.abs(deltaX) < menuWidth){
                        scrollTo(menuWidth * menuViews.size(), 0);
                        isMenuOpen = true;
                    }else{
                        scrollTo(0,0);
                        isMenuOpen = false;
                    }
                }
            }
        }
    
        public void scrollBack(){
            scrollTo(0,0);
            isMenuOpen = false;
        }
    }

    在attr文件中定义

    <declare-styleable name="CustomSlideDeleteItemView">
            <attr name="contentViewId" format="integer"/>
        </declare-styleable>

    然后定义我们的CustomSlideDeleteListView

    package com.example.myapp.view;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Color;
    import android.graphics.drawable.ColorDrawable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.widget.ListView;
    
    import com.example.myapp.R;
    
    /**
     * Created by zyr
     * DATE: 16-3-18
     * Time: 下午5:42
     * Email: yanru.zhang@renren-inc.com
     */
    public class CustomSlideDeleteListView extends ListView {
        private Context mContext;
        private CustomSlideDeleteItemView mCurrentView;
        private int currentItemId;
        private int downX,downY,moveX,moveY,deltaX,deltaY,upX,upY,lastX,lastDeltaX;
        public final static int MIN_SCROLL_DIS = 100;
        public CustomSlideDeleteListView(Context context) {
            this(context, null);
        }
    
        public CustomSlideDeleteListView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CustomSlideDeleteListView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            setSelector(new ColorDrawable(Color.TRANSPARENT));
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomSlideDeleteListView);
            for(int i=0;i<typedArray.length();i++){
                int attr = typedArray.getIndex(i);
                switch (attr){
                    case R.styleable.CustomSlideDeleteListView_rightViewId:
    
                        break;
                }
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            switch (ev.getAction()){
                case MotionEvent.ACTION_DOWN:
                    lastX = downX = (int) ev.getX();
                    downY = (int) ev.getY();
                    currentItemId = pointToPosition(downX, downY);
                    mCurrentView = (CustomSlideDeleteItemView)getChildAt(currentItemId - getFirstVisiblePosition());
    //                Log.e("zyr","currentItemId:" + currentItemId);
                    break;
                case MotionEvent.ACTION_MOVE:
                    /**还要区分上下滑动listview的时候**/
                    moveX = (int) ev.getX();
                    moveY = (int) ev.getY();
                    deltaX = moveX - downX;
                    deltaY = moveY - downY;
                    if(Math.abs(deltaX) > Math.abs(deltaY)){
                        lastDeltaX = moveX - lastX;
                        lastX = moveX;
    //                Log.d("zyr","deltaX:" + deltaX);
    //                Log.e("zyr","canShowRightView " + canShowRightView);
                        if(Math.abs(deltaX) > MIN_SCROLL_DIS && mCurrentView!=null){
                            mCurrentView.scroll(deltaX,lastDeltaX);
                            return true;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    upX = (int)ev.getX();
                    upY = (int)ev.getY();
                    if(mCurrentView!=null && Math.abs(upX-downX) > MIN_SCROLL_DIS){
                        mCurrentView.autoScroll(upX-downX);
                    }
                    break;
            }
            return super.onTouchEvent(ev);
        }
    }

    最后需要定义我们的Adapter

    package com.example.myapp.adapter;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.Filter;
    import android.widget.Filterable;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.example.myapp.R;
    import com.example.myapp.view.CustomSlideDeleteItemView;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by zyr
     * DATE: 15-11-26
     * Time: 下午2:52
     * Email: yanru.zhang@renren-inc.com
     */
    public class CustomSlideDeleteListViewAdapter extends BaseAdapter implements Filterable{
        public List<String> arrayList = new ArrayList<String>();
        private Context context;
        private MyFilter mFilter;
    
        public CustomSlideDeleteListViewAdapter(Context context){
            this.context = context;
        }
        public CustomSlideDeleteListViewAdapter(Context context, List<String> arrayList){
            this.context = context;
            this.arrayList = new ArrayList<String>(arrayList);
        }
    
        public void setData(List<String> array){
            if(array ==null){
                return;
            }
            arrayList = new ArrayList<String>(array);
            notifyDataSetChanged();
        }
        @Override
        public int getCount() {
            return arrayList.size();
        }
    
        @Override
        public Object getItem(int position) {
            return arrayList.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;
            if(convertView ==null){
                convertView = LayoutInflater.from(context).inflate(R.layout.list_view_item,null);
                viewHolder = new ViewHolder(convertView);
                convertView.setTag(viewHolder);
            }else{
                viewHolder = (ViewHolder)convertView.getTag();
            }
            viewHolder.itemView.clearAllMenu();
            viewHolder.itemView.addMenu("Delete", Color.RED);
            viewHolder.itemView.addMenu("Open", Color.BLUE);
            viewHolder.itemView.scrollBack();
            viewHolder.textView.setText(arrayList.get(position));
            viewHolder.itemView.setOnMenuClickListener(new CustomSlideDeleteItemView.OnMenuClickListener() {
                @Override
                public void onMenuClick(int i, int counts) {
                    switch (i){
                        case 0:
                            arrayList.remove(position);
                            notifyDataSetChanged();
                            break;
                        case 1:
                            break;
                    }
    
                }
            });
            return convertView;
        }
    
        @Override
        public Filter getFilter() {
            if (mFilter == null) {
                mFilter = new MyFilter();
            }
            return mFilter;
        }
        class MyFilter extends Filter {
    
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                if (arrayList == null) {
                    arrayList = new ArrayList<String>();
                }
                results.values = arrayList;
                results.count = arrayList.size();
                return results;
            }
    
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    
        class ViewHolder{
            CustomSlideDeleteItemView itemView;
            TextView textView;
            public ViewHolder(View view){
                itemView = (CustomSlideDeleteItemView)view;
                textView = (TextView)view.findViewById(R.id.list_view_text);
            }
        }
    }

    adapter引用的xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <com.example.myapp.view.CustomSlideDeleteItemView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:background="@drawable/common_listview_bg"
        app:contentViewId="@+id/list_view_text">
        <TextView android:id="@+id/list_view_text"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:textColor="@color/primary"
            android:textStyle="bold"
            android:paddingLeft="20dp" />
    </com.example.myapp.view.CustomSlideDeleteItemView>

    在Activity中引用

      customSlideDeleteListView = (CustomSlideDeleteListView) findViewById(R.id.custom_slid_delete_list_view);
            for(int i=0;i<100;i++){
                stringList.add("zyr" + i);
            }
            customSlideDeleteListViewAdapter = new CustomSlideDeleteListViewAdapter(this,stringList);
            customSlideDeleteListView.setAdapter(customSlideDeleteListViewAdapter);
  • 相关阅读:
    pytorch——nn.Module
    jQuery性能优化的28个建议
    javascript string 转 date
    javascript 追加date format属性。
    javascript翻页小控件paginator
    getTime()的00:00:00问题。
    禁止输入表情的方法
    解决带有导航的情况下 关于present自动返回的问题
    设置透明色
    class can not be find with platformType:1 step 1
  • 原文地址:https://www.cnblogs.com/bbglz/p/5305873.html
Copyright © 2020-2023  润新知