1.需求
1.1实现一个类似QQ的ListView侧滑菜单,
分析一下都有哪些要求:
- 可以侧滑拉出菜单
- 点击时如果不是点击已经打开的item需关闭之前的item
- 点击时如果是已经打开的item,则可以继续拉动
2.实现
2.1先继承HorizontalScrollView实现一个类,便于布局
package com.example.scrolllistview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ScrollListView extends HorizontalScrollView{
//记录各个宽度
private int wScreen;
private int wButton;
private boolean once;
private Button leftbtn;
private Button rightbtn;
private TextView tx;
//构造方法
public ScrollListView(Context context) {
super(context,null);
}
public ScrollListView(Context context ,AttributeSet set)
{
super(context,set,0);
}
public ScrollListView(Context context ,AttributeSet set ,int defStyle) {
super(context,set,defStyle);
}
//重载测量方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!once)
{
//获得第一个布局
LinearLayout linearlayout = (LinearLayout)getChildAt(0);
leftbtn = (Button)linearlayout.getChildAt(0);
tx = (TextView)linearlayout.getChildAt(1);
rightbtn = (Button)linearlayout.getChildAt(2);
//获得屏幕的宽度
WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
//Onmeasure方法会被多次使用,造成频繁的创建销毁对象,为了ui的性能建议不要这样使用
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
wScreen = outMetrics.widthPixels;
wButton = wScreen/2;
//设置个子控件的宽度
leftbtn.getLayoutParams().width = wButton;
tx.getLayoutParams().width = wScreen;
rightbtn.getLayoutParams().width = wButton;
this.getParent();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//重载布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//如果改变
if(changed)
{
//将view滑动到(x,y)处 坐标原点parentview 左上角
this.scrollTo(wButton, 0);
once = true;
}
}
@Override
public boolean performClick() {
return super.performClick();
}
public void close()
{
this.scrollTo(wButton, 0);
}
public void open()
{
this.scrollTo(wButton+wScreen, 0);
}
}
2.2编写listview的item布局
<com.example.scrolllistview.ScrollListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80sp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/leftbtn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#303F9F"
android:text="@string/leftbtn"/>
<TextView
android:id="@+id/context"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/context"/>
<Button
android:id="@+id/rightbtn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#303F9F"
android:text="@string/rightbtn"/>
</LinearLayout>
</com.example.scrolllistview.ScrollListView>
2.3编写适配器类
package com.example.scrolllistview;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
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.Button;
import android.widget.ListView;
import android.widget.TextView;
public class ModelAdapter extends BaseAdapter{
private boolean isMove;
private int oldItem = -1;
private ListView list;
private boolean closed = true;
private Context tx;
private int resourceID;
private List<Model> mlist;
public ModelAdapter(Context tx, int resourceid ,List<Model> list ,ListView listview) {
// TODO Auto-generated constructor stub
this.tx = tx;
this.resourceID = resourceid;
this.mlist = list;
this.list = listview;
}
@Override
public int getCount() {
return mlist.size();
}
@Override
public Object getItem(int position) {
return mlist.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
Model m = (Model)getItem(position);
if(convertView == null)
{
convertView = LayoutInflater.from(tx).inflate(this.resourceID, parent,false);
vh = new ViewHolder();
vh.leftbtn = (Button)convertView.findViewById(R.id.leftbtn);
vh.context = (TextView)convertView.findViewById(R.id.context);
vh.rightbtn = (Button)convertView.findViewById(R.id.rightbtn);
convertView.setTag(vh);
}
else
{
vh = (ViewHolder)convertView.getTag();
}
vh.leftbtn.setText(m.getLeftText());
vh.rightbtn.setText(m.getRigthText());
vh.context.setText(m.getContext());
//告知点击事件点击的是哪一个item
vh.context.setTag(position);
//点击事件
convertView.setOnTouchListener(new OnTouchListener() {
float oldX = 0;
int f = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
ViewHolder viewHolder = new ViewHolder();
viewHolder = (ViewHolder) v.getTag();
//获得点击的位置
//如果是全部关闭的可以移动
if(oldItem == (Integer)viewHolder.context.getTag() || closed)
{
isMove = true;
oldItem = (Integer)viewHolder.context.getTag();
}
else
{
isMove = false;
}
break;
case MotionEvent.ACTION_MOVE:
//获得当前屏幕内可见的第一个
f = list.getFirstVisiblePosition();
//获得点击得位置
if(!isMove)
{
((ScrollListView)list.getChildAt(oldItem-f)).close();
closed = true;
event.setAction(MotionEvent.ACTION_CANCEL);
}
else
closed = false;
case MotionEvent.ACTION_UP:
float newX = event.getX();
if(oldX == newX)
{
((ScrollListView)list.getChildAt(oldItem-f)).close();
closed = true;
event.setAction(MotionEvent.ACTION_CANCEL);
}
default:
break;
}
return false;
}
});
//按钮的单击事件
vh.rightbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//获得当前点击哪个item
v.setBackgroundColor(Color.RED);
}
});
return convertView;
}
class ViewHolder
{
public Button leftbtn;
public TextView context;
public Button rightbtn;
}
}
2.4编写主页面的布局,就一个listview
<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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ListView
android:id="@+id/lview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
2.5Activity
package com.example.scrolllistview;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView list = (ListView)findViewById(R.id.lview);
//准备数据
List<Model> mList = new ArrayList<Model>();
for(int i=0;i<10;i++)
{
Model m = new Model("leftbtn"+i,"context"+i,"rightbtn"+i);
mList.add(m);
}
//适配器
ModelAdapter adapter = new ModelAdapter(MainActivity.this, R.layout.slistitem, mList,list);
list.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
不提倡这样写,应该使用handler为主线程投递message,让主线程只负责布局。