仿QQ侧滑删除(简陋版)

来源:互联网 发布:海洋cms模板怎么用 编辑:程序博客网 时间:2024/06/07 10:17
 今天想试试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侧滑删除。

0 0
原创粉丝点击