使用HorizontalScrollView实现侧滑ListView

1.需求

1.1实现一个类似QQ的ListView侧滑菜单,

分析一下都有哪些要求:

  1. 可以侧滑拉出菜单
  2. 点击时如果不是点击已经打开的item需关闭之前的item
  3. 点击时如果是已经打开的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,让主线程只负责布局。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值