Android常用组件——定制化的SwipeListView

来源:互联网 发布:淘宝店怎么改名字 编辑:程序博客网 时间:2024/05/22 17:14

1、背景介绍

其实要实现的东西并不算太复杂,类似于QQ那样的ListView横向滑动展现删除控件而已。图示,如下:



2、SwipeListView

介绍一下,我在最开始实现这样的功能的时候,找到的是这样的一个开源控件,名字如标题,地址是:https://github.com/47deg/android-swipelistview

大家可以直接在GitHub上去看,不过这个项目的注释写得可能有些不太清楚,简单列举一些它的属性如下:

swipeFrontView - Required - front view id. 即ListView Item正常显示的控件Id,且必须与Item的布局文件中的控件id一样swipeBackView - Required - back view id.  手指滑动时显示的,隐藏在FrontView后面,且必须与item的布局文件中控件Id一样swipeActionLeft - Optional - left swipe action Default: 'reveal'  左滑的动作,默认reveal,即显示BackView,还有dismiss,choice会触发响应的方法。swipeActionRight - Optional - right swipe action Default: 'reveal' 同上swipeMode - Gestures to enable or 'none'. Default: 'both' 设置左滑、右滑、都支持swipeCloseAllItemsWhenMoveList - Close revealed items on list motion. Default: 'true' 当滚动listview时,关闭所有展开的Item,最好不要设置为false,由于item的复用,false存在一些问题。swipeOpenOnLongPress - Reveal on long press Default: 'true' 长按时触发显示swipeAnimationTime - item drop animation time. Default: android configuration 动画时间长度swipeOffsetLeft - left offset 左偏移量swipeOffsetRight - right offset 右偏移量

使用的代码,XML文件代码如下:

<com.fortysevendeg.swipelistview.SwipeListView            xmlns:swipe="http://schemas.android.com/apk/res-auto"            android:id="@+id/example_lv_list"            android:listSelector="#00000000"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            swipe:swipeFrontView="@+id/front"            swipe:swipeBackView="@+id/back"            swipe:swipeActionLeft="[reveal | dismiss]"            swipe:swipeActionRight="[reveal | dismiss]"            swipe:swipeMode="[none | both | right | left]"            swipe:swipeCloseAllItemsWhenMoveList="[true | false]"            swipe:swipeOpenOnLongPress="[true | false]"            swipe:swipeAnimationTime="[miliseconds]"            swipe:swipeOffsetLeft="[dimension]"            swipe:swipeOffsetRight="[dimension]"            />


比较简单,直接使用SwipeListView替换原来的ListView即可。

可能接下来会有一个比较容易出错的地方,这里官方文档也没有提及,就是布局文件是两层覆盖的,菜单那一层在下面,但是写代码的时候,在XML文件的上半部分,我们看一个简单的框架案例:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="60dp" >    <LinearLayout        android:id="@+id/id_back"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#ffcccccc"        android:gravity="center|right" >        <Button            android:id="@+id/id_remove"            android:layout_width="60dp"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_marginRight="4dp"            android:background="@drawable/red_button"            android:text="Delete"            android:textColor="#fff" >        </Button>    </LinearLayout>    <LinearLayout        android:id="@+id/id_front"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#ffffffff" >        <TextView            android:id="@+id/id_text"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginLeft="10dp"            android:gravity="center_vertical"            android:minHeight="?android:attr/listPreferredItemHeight"            android:textAppearance="?android:attr/textAppearanceLarge"            android:textColor="#000"            android:textSize="25sp" >        </TextView>    </LinearLayout></FrameLayout>

如上就是一个item的布局文件,一定要注意两个Layout的id值,不能修改!!!一定要是back和front,不然程序会报错一个无法找到文件的错误。

不过这个代码,无法实现如上图的扁平化的风格。我只好重新试试别的方法。


3、SwipeMenuListView

这个控件没怎么看到有人提及,也可能是这个控件不如上面那一个出来得早的缘故吧。现在也给出github上的地址,如下:https://github.com/baoyongzhang/SwipeMenuListView

这个就不多说了,给一个案例吧,作者自己的代码,代码不多,核心代码也就只有几句话,如下:

public class SimpleActivity extends Activity {    private List<ApplicationInfo> mAppList;    private AppAdapter mAdapter;    private SwipeMenuListView mListView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_list);        mAppList = getPackageManager().getInstalledApplications(0);        mListView = (SwipeMenuListView) findViewById(R.id.listView);        mAdapter = new AppAdapter();        mListView.setAdapter(mAdapter);        // step 1. create a MenuCreator        SwipeMenuCreator creator = new SwipeMenuCreator() {            @Override            public void create(SwipeMenu menu) {                // create "open" item                SwipeMenuItem openItem = new SwipeMenuItem(                        getApplicationContext());                // set item background                openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,                        0xCE)));                // set item width                openItem.setWidth(dp2px(90));                // set item title                openItem.setTitle("Open");                // set item title fontsize                openItem.setTitleSize(18);                // set item title font color                openItem.setTitleColor(Color.WHITE);                // add to menu                menu.addMenuItem(openItem);                // create "delete" item                SwipeMenuItem deleteItem = new SwipeMenuItem(                        getApplicationContext());                // set item background                deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,                        0x3F, 0x25)));                // set item width                deleteItem.setWidth(dp2px(90));                // set a icon                deleteItem.setIcon(R.drawable.ic_delete);                // add to menu                menu.addMenuItem(deleteItem);            }        };        // set creator        mListView.setMenuCreator(creator);        // step 2. listener item click event        mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {            @Override            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {                ApplicationInfo item = mAppList.get(position);                switch (index) {                    case 0:                        // open                        open(item);                        break;                    case 1:                        // delete//delete(item);                        mAppList.remove(position);                        mAdapter.notifyDataSetChanged();                        break;                }                return false;            }        });        // set SwipeListener        mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {            @Override            public void onSwipeStart(int position) {                // swipe start            }            @Override            public void onSwipeEnd(int position) {                // swipe end            }        });        // set MenuStateChangeListener        mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {            @Override            public void onMenuOpen(int position) {            }            @Override            public void onMenuClose(int position) {            }        });        // other setting//listView.setCloseInterpolator(new BounceInterpolator());        // test item long click        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {            @Override            public boolean onItemLongClick(AdapterView<?> parent, View view,                                           int position, long id) {                Toast.makeText(getApplicationContext(), position + " long click", Toast.LENGTH_SHORT).show();                return false;            }        });    }    private void delete(ApplicationInfo item) {        // delete app        try {            Intent intent = new Intent(Intent.ACTION_DELETE);            intent.setData(Uri.fromParts("package", item.packageName, null));            startActivity(intent);        } catch (Exception e) {        }    }    private void open(ApplicationInfo item) {        // open app        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);        resolveIntent.setPackage(item.packageName);        List<ResolveInfo> resolveInfoList = getPackageManager()                .queryIntentActivities(resolveIntent, 0);        if (resolveInfoList != null && resolveInfoList.size() > 0) {            ResolveInfo resolveInfo = resolveInfoList.get(0);            String activityPackageName = resolveInfo.activityInfo.packageName;            String className = resolveInfo.activityInfo.name;            Intent intent = new Intent(Intent.ACTION_MAIN);            intent.addCategory(Intent.CATEGORY_LAUNCHER);            ComponentName componentName = new ComponentName(                    activityPackageName, className);            intent.setComponent(componentName);            startActivity(intent);        }    }    class AppAdapter extends BaseAdapter {        @Override        public int getCount() {            return mAppList.size();        }        @Override        public ApplicationInfo getItem(int position) {            return mAppList.get(position);        }        @Override        public long getItemId(int position) {            return position;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            if (convertView == null) {                convertView = View.inflate(getApplicationContext(),                        R.layout.item_list_app, null);                new ViewHolder(convertView);            }            ViewHolder holder = (ViewHolder) convertView.getTag();            ApplicationInfo item = getItem(position);            holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));            holder.tv_name.setText(item.loadLabel(getPackageManager()));            return convertView;        }        class ViewHolder {            ImageView iv_icon;            TextView tv_name;            public ViewHolder(View view) {                iv_icon = (ImageView) view.findViewById(R.id.iv_icon);                tv_name = (TextView) view.findViewById(R.id.tv_name);                view.setTag(this);            }        }    }    private int dp2px(int dp) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,                getResources().getDisplayMetrics());    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.menu_main, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        int id = item.getItemId();        if (id == R.id.action_left) {            mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);            return true;        }        if (id == R.id.action_right) {            mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_RIGHT);            return true;        }        return super.onOptionsItemSelected(item);    }}

4、总结

在3中使用的控件,可以实现我们想要的效果。但是相对来说,2中的控件的设计模式更适合扩展,耦合性更低一些,3中的设计不是那么好用。

将就一下,之后再去更改吧。说个题外话,如果是嵌套使用了ScrollView,那么最好在ListView中重写如下的方法:

// 重写,适应外层嵌套ScrollView    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,                MeasureSpec.AT_MOST);        super.onMeasure(widthMeasureSpec, expandSpec);    }


0 0