仿QQ侧滑删除(简陋版)

 今天想试试android View的事件分发机制,于是自制了一个仿QQ的侧滑删除当小白鼠,利用这个来验证View面对不同的情况下,的事件分发情况。
 由于是当给自己当试验品用,做的有点简陋,不对那可是相当简陋。
 原理:首先一个全屏的item加上一个button拼接成一个HorizontalScrollView。让button显示在屏幕的外面,当侧滑的时候显示出button。之后放入listview中
 效果图:![仿QQ侧滑删除](http://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侧滑删除。

你可能感兴趣的:(android,ListView)