仿QQ侧滑删除(简陋版)

Posted 從前以後

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了仿QQ侧滑删除(简陋版)相关的知识,希望对你有一定的参考价值。

 今天想试试android View的事件分发机制,于是自制了一个仿QQ的侧滑删除当小白鼠,利用这个来验证View面对不同的情况下,的事件分发情况。
 由于是当给自己当试验品用,做的有点简陋,不对那可是相当简陋。
 原理:首先一个全屏的item加上一个button拼接成一个HorizontalScrollView。让button显示在屏幕的外面,当侧滑的时候显示出button。之后放入listview中
 效果图:![仿QQ侧滑删除](https://img-blog.csdn.net/20151209164737710)
 首先还是自定义View第一步:values 下的attr
<?xml version="1.0" encoding="utf-8"?>
<resources>    
    <attr name="width_ethan" format="dimension"/>
    <declare-styleable name="Ethan">        
        <attr name="width_ethan"/>
    </declare-styleable>
</resources>

attr 定义了一个宽度,这个宽度也就是后来的删除button的宽度,也是侧滑的最大距离。
接下来就是自定义MyView了

package com.example.tencent;

import com.example.day.activity.utils.ScreenUtils;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class MyView extends HorizontalScrollView
    private int width;
    private int mScreenWidth;//屏幕宽度
    private float halfwidth;

    public MyView(Context context, AttributeSet attrs) 
        this(context, attrs,0);
        mScreenWidth=ScreenUtils.getScreenWidth(context);
    
    public MyView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);
        TypedArray a=getContext().getTheme().obtainStyledAttributes(attrs,R.styleable.Ethan,defStyle,0);
        int count=a.getIndexCount();
        for(int i=0;i<count;i++)
        
            int attr=a.getIndex(i);
            switch (attr) 
            case R.styleable.Ethan_width_ethan:
                width=a.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()));       
                halfwidth=width/2;
                break;
            
            a.recycle();
        
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        LinearLayout  ly = (LinearLayout) getChildAt(0);
        View list=ly.getChildAt(0);
        View button=ly.getChildAt(1);
        button.getLayoutParams().width=width;
        list.getLayoutParams().width=mScreenWidth;
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) 
        // TODO 自动生成的方法存根
        return false;
    
    @Override
    public boolean onTouchEvent(MotionEvent ev) 
        super.onTouchEvent(ev);
        int action = ev.getAction();
        switch (action) 
        case MotionEvent.ACTION_UP:
        int scrollX = getScrollX();
              if(Math.abs(scrollX)>halfwidth)
              

                 this. smoothScrollTo(width,0);
              
              else
              
                 this. smoothScrollTo(0,0);

                   
            break;  
        
        //return false;
        return true;        
        //return super.onTouchEvent(ev);
    


MyView里面首先是二参数构造方法来调用三参数的构造方法,并且获取了屏幕的宽度大小。接着三个参数构造方法拿到typedArray 对象a。a也就对应着attr里面对应的自定义列表项。通过a可以拿到定义的width_ethan的值,也就是自定义删除按钮的宽度。

紧接着在onMeasure()方法中拿到该布局下的两个子View(item和button)的对象,
然后设置两个对象的LayoutParams,之后进行测量。测量调用的view中的LayoutParams就是设置的。
测量完成后重写MyView的onTouchEvent()方法,首先拿到当前的点击事件,当
ACTION_UP执行时,也就是一次用户手操作完毕时。判断滑动的距离,如果距离大于删除button的一般就采用smoothScrollTo平滑过去,反之回到原状态。
注意:onTouchEvent()返回值一定要为true,否则该方法执行不了,返回到上一层次的onTouchEvent()方法(View的事件分发机制);
之后主布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="450dp"
    android:layout_height="50dp"
    android:id="@+id/list"
    android:background="@android:color/holo_purple"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/title_text"
        android:text="标题"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
     <TextView
        android:id="@+id/context_text"
        android:text="内容"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
<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:id="@+id/layout"
   android:focusable="true"
       android:focusableInTouchMode="true"
    tools:context=".MainActivity" >

    <ListView
       android:focusable="true"
       android:focusableInTouchMode="true"
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</RelativeLayout>

接下来就是MyAdapter了

package com.example.tencent;

import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter 
    private List<Item> list;
    private LayoutInflater layoutInflater;

    public MyAdapter(Context context, List<Item> list) 
        this.list = list;
        layoutInflater = LayoutInflater.from(context);
    

    @Override
    public int getCount() 

        return list.size();
    

    @Override
    public Object getItem(int position) 

        return list.get(position);
    

    @Override
    public long getItemId(int position) 
        // TODO 自动生成的方法存根
        return position;
    

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) 
        ViewHolder viewHolder;
        if (convertView == null) 
            viewHolder = new ViewHolder();
            convertView = layoutInflater.inflate(R.layout.my_view, null);
            viewHolder.title = (TextView) convertView
                    .findViewById(R.id.title_text);
            viewHolder.context = (TextView) convertView
                    .findViewById(R.id.context_text);
            viewHolder.button = (TextView) convertView
                    .findViewById(R.id.del_button);
            viewHolder.ly=(LinearLayout) convertView.findViewById(R.id.list);
            convertView.setTag(viewHolder);
         else 
            viewHolder = (ViewHolder) convertView.getTag();
        
        viewHolder.title.setText(list.get(position).getName());
        viewHolder.context.setText(list.get(position).getAge());
      viewHolder.ly.setOnTouchListener(new OnTouchListener() 

        @Override
        public boolean onTouch(View v, MotionEvent event) 

            Log.i("ethan", "ly ontouch");
            return false;
        
    );
        viewHolder.button.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View v) 
            list.remove(position);
            notifyDataSetChanged();

            
        );
        return convertView;
    

    class ViewHolder 
        TextView title, context;
        TextView button;
        LinearLayout ly;
    


MyAdapter里面就是一般的实现BaseAdapter的步骤。这里对button设置了一个点击事件来移除list,同时对布局设置了一个ontouch(该方法纯属测试View的事件分发用);
接下来就是MainActivity了

package com.example.tencent;

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

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;



public class MainActivity extends Activity

    private List<Item>list;
    private ListView listview;
    private RelativeLayout rl;
    private View myView;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        // TODO 自动生成的方法存根
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        listview=(ListView) findViewById(R.id.listview);
        rl=(RelativeLayout) findViewById(R.id.layout);
        list=new ArrayList<Item>();


        MyAdapter my=new MyAdapter(this, list);

        for(int i=0;i<11;i++)
        
            Item item=new Item();
            item.setName("Ethan");
            item.setAge(i+"");
            list.add(item);
        


        listview.setAdapter(my);

        listview.setOnTouchListener(new OnTouchListener() 

            @Override
            public boolean onTouch(View v, MotionEvent event) 
                Log.e("ethan", "listview on touch run");
                return false;
            
        );
        listview.setOnItemClickListener(new OnItemClickListener() 

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                    long id) 
                // TODO 自动生成的方法存根
                Log.e("ethan", "listview on click run");
                Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
            
        );
    

MainActivity里面就是一般的listview的setAdapter方法。中间的两个setOnTouchListener和setOnItemClickListener是作为测试View的事件分发用的。
OK 大功告成,简陋版仿QQ侧滑删除。

以上是关于仿QQ侧滑删除(简陋版)的主要内容,如果未能解决你的问题,请参考以下文章

仿QQ侧滑删除Item:Swipemenulistview的简单实现

仿QQ侧滑删除Item:Swipemenulistview的简单实现

仿今日头条和qq侧滑和智慧北京的小项目 3

OC仿QQ侧滑

Android使用DrawerLayout仿qq6.6版本侧滑效果

小程序仿QQ侧滑例子