仿ios短信列表滑动出现删除按钮
2016-06-07 19:52
423 查看
最近还没找到工作所以在宿舍有点闲,所以呢就自己写了这么一个例子。之前网上有很多人写过类似的文章或demo,github上面也有开源项目。但是,老是copy别人代码也怪没意思的,于是就自己尝试着自己写呗。废话多了先来看下效果咯:
运行效果:
1、实现思路
其实实现思路很简单那就是在ListView的item里面放一个可以滑动的view,这里我用的是HorizontalScrollView。我之所以选HorizontalScrollView是因为可以不用去处理move事件
2、SildingView的实现
SildingView是我自定义的一个View 他继承的是HorizontalScrollView,SildingView就是我们要放到ListView item里面的View。代码如下所示:
SlideView.java
3、Activity的实现
同样也是将MainActivity的代码全部贴出来,为了方便我写了一个静态内部的Adapter。在getView()方法中将第三个参数强制转化为SildingView,然后定义一个item_view来获取加载好的布局文件,再将item_view做为SildingView的内容添加进去,最后返回SildingView。这样就很好的实现了将SildingView做为ListView的item添加进去,呃描述的实在不好能力有限啊还是看代码理解吧。。。。
如果仔细一点会发现iphone手机短信列表,如果有一个item的ItemMenu处于打开状态那么接下来无论用户是滑动列表还是点击列表的item都将没有应有的效果,而产生的效果就是将打开的ItemMenu关闭。为了实现这个效果我重写了ListView的onTouch()方法,在move事件中通过遍历ListView的所有item来检查是否有item的ItemMenu已经打开如果有则将其关闭并且屏蔽掉onTouchEvent()方法使得ListView无法滑动。最后一个问题就是item的点击事件的问题,因为我们将View换成了SlidingView(SlidingView是一个HorizontalScrollView,而HorizontalScrollView貌似将click事件屏蔽掉了)导致我们给ListView设置onItemClick事件失效,因此我选择在getView()方法中设置SlidingView中的子View的click事件这样同样实现了ListView的调集效果。但是这绝对不是最好的方法
4、布局文件
activity_main.xml
item.xml
运行效果:
1、实现思路
其实实现思路很简单那就是在ListView的item里面放一个可以滑动的view,这里我用的是HorizontalScrollView。我之所以选HorizontalScrollView是因为可以不用去处理move事件
2、SildingView的实现
SildingView是我自定义的一个View 他继承的是HorizontalScrollView,SildingView就是我们要放到ListView item里面的View。代码如下所示:
SlideView.java
package okhttp.lc.com.lateralslidingitem; import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.Scroller; /** * Created by HP on 2016/6/6. */ public class SildingView extends HorizontalScrollView { int mScreenWidth; boolean once = false; //将MenuItem的宽度设置为100px int MenuWidth = 100; LinearLayout wapperView; LinearLayout mContent; LinearLayout mMenu; OpenStatusListener mListener; //判断菜单是否打开 boolean isOpen = false; public SildingView(Context context) { this(context, null); } public SildingView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SildingView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public void setContent(View view) { addView(view); } private void init(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); mScreenWidth = outMetrics.widthPixels; } /** * 设置ItemMenu打开监听事件 * @param mListener */ public void setOpenStatusListener(OpenStatusListener mListener) { this.mListener = mListener; } public interface OpenStatusListener { //status 0表示打开 1表示关闭 void getOpenStatus(int status); } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_UP: { if (getScrollX() >= MenuWidth / 2) { smoothScrollTo(MenuWidth, 0); isOpen = true; mListener.getOpenStatus(0); } else { smoothScrollTo(0, 0); isOpen = false; mListener.getOpenStatus(1); } } return true; } return super.onTouchEvent(ev); } /** * 打开ItemMenu */ public void openItemMenu() { if (!isOpen) { smoothScrollTo(MenuWidth, 0); isOpen = true; mListener.getOpenStatus(0); } } public boolean getStatus() { return isOpen; } /** * 关闭ItemMenu */ public void closeItemMenu() { if (isOpen) { smoothScrollTo(0, 0); isOpen = false; mListener.getOpenStatus(1); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //onMeasure会多次调用,用once来控制以防多次执行以下代码 if (!once) { wapperView = (LinearLayout) getChildAt(0); mContent = (LinearLayout) wapperView.getChildAt(0); mMenu = (LinearLayout) wapperView.getChildAt(1); mContent.getLayoutParams().width = mScreenWidth; mMenu.getLayoutParams().width = MenuWidth; once = true; } } }
3、Activity的实现
package okhttp.lc.com.lateralslidingitem; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { ListView lv_main; List<String> list = new ArrayList<String>(); okhttp.lc.com.lateralslidingitem.SildingView mSlidingView; MyAdapter adapter; boolean isOpen = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initData(); } private void initData() { for (int i = 0; i < 40; i++) { list.add("SomeThing" + (i + 1)); } adapter = new MyAdapter(this); lv_main.setAdapter(adapter); /** * 监听ListView的滑动 */ lv_main.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { int action = motionEvent.getAction(); if (check()) { Log.e("TAG", "true"); switch (action) { case MotionEvent.ACTION_DOWN: { close(); } break; case MotionEvent.ACTION_MOVE: { close(); } break; case MotionEvent.ACTION_UP: { close(); } break; } return true; } return false; } }); } /** * 关闭ItemMenu */ private void close() { Log.e("TAG", "close"); for (int i = 0; i < lv_main.getChildCount(); i++) { SildingView v = (SildingView) lv_main.getChildAt(i); v.closeItemMenu(); } } /** * 检查是否有打开的ItemMenu * @return */ private boolean check() { for (int i = 0; i < lv_main.getChildCount(); i++) { SildingView v2 = (SildingView) lv_main.getChildAt(i); if (v2.getStatus()) { isOpen = true; return isOpen; } } return false; } private void initViews() { lv_main = (ListView) findViewById(R.id.lv_main); } class MyAdapter extends BaseAdapter implements SildingView.OpenStatusListener { private LayoutInflater mInflater; private Context mContext; MyAdapter(Context mContext) { this.mContext = mContext; mInflater = LayoutInflater.from(mContext); } @Override public int getCount() { return list.size(); } @Override public Object getItem(int i) { return list.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder mViewHolder = null; mSlidingView = (SildingView) view; if (mSlidingView == null) { mViewHolder = new ViewHolder(); View itemview = mInflater.inflate(R.layout.item, null); mSlidingView = new SildingView(MainActivity.this); /** * 貌似HorizontalScrollView的click事件被屏蔽了,应此为了实现点击效果采用了这种方法。 */ final LinearLayout ll_item = (LinearLayout) itemview.findViewById(R.id.ll_item); final int in=i; ll_item.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (check()) { close(); } else Toast.makeText(getApplicationContext(), "click" + in, Toast.LENGTH_SHORT).show(); } }); mSlidingView.setContent(itemview); mSlidingView.setOpenStatusListener(this); mViewHolder.textView = (TextView) mSlidingView.findViewById(R.id.textView); mViewHolder.delete = (TextView) mSlidingView.findViewById(R.id.delete); mSlidingView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) mSlidingView.getTag(); } mViewHolder.textView.setText(getItem(i).toString()); mViewHolder.delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getApplicationContext(), "delete", Toast.LENGTH_LONG).show(); } }); return mSlidingView; } @Override public void getOpenStatus(int status) { if (status == 0) { Toast.makeText(getApplicationContext(), "打开", Toast.LENGTH_SHORT).show(); // isOpen = true; } else { Toast.makeText(getApplicationContext(), "关闭" , Toast.LENGTH_SHORT).show(); // isOpen = false; } } } class ViewHolder { TextView textView; TextView delete; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { Intent intent = new Intent(); intent.setClass(MainActivity.this, Activity2.class); startActivity(intent); return true; } return super.onOptionsItemSelected(item); } }
同样也是将MainActivity的代码全部贴出来,为了方便我写了一个静态内部的Adapter。在getView()方法中将第三个参数强制转化为SildingView,然后定义一个item_view来获取加载好的布局文件,再将item_view做为SildingView的内容添加进去,最后返回SildingView。这样就很好的实现了将SildingView做为ListView的item添加进去,呃描述的实在不好能力有限啊还是看代码理解吧。。。。
如果仔细一点会发现iphone手机短信列表,如果有一个item的ItemMenu处于打开状态那么接下来无论用户是滑动列表还是点击列表的item都将没有应有的效果,而产生的效果就是将打开的ItemMenu关闭。为了实现这个效果我重写了ListView的onTouch()方法,在move事件中通过遍历ListView的所有item来检查是否有item的ItemMenu已经打开如果有则将其关闭并且屏蔽掉onTouchEvent()方法使得ListView无法滑动。最后一个问题就是item的点击事件的问题,因为我们将View换成了SlidingView(SlidingView是一个HorizontalScrollView,而HorizontalScrollView貌似将click事件屏蔽掉了)导致我们给ListView设置onItemClick事件失效,因此我选择在getView()方法中设置SlidingView中的子View的click事件这样同样实现了ListView的调集效果。但是这绝对不是最好的方法
4、布局文件
activity_main.xml
<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" tools:context=".MainActivity"> <ListView android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:descendantFocusability="blocksDescendants" android:id="@+id/ll_item" android:orientation="horizontal"> <LinearLayout android:id="@+id/ll_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#50000000" > <TextView android:id="@+id/delete" android:layout_width="match_parent" android:layout_height="match_parent" android:text="delete" android:gravity="center" /> </LinearLayout> </LinearLayout>
相关文章推荐
- iOS——音频封装
- iOS中 视频直播功能-流媒体的使用(详解)韩俊强的CSDN博客
- iOS中 视频直播功能-流媒体的使用(详解)韩俊强的CSDN博客
- iOS开发---常用公用方法
- iOS9 Search API 之 Spotlight
- iOS开发编码及命名规范
- IOS浏览带目录pdf,缩放实现
- iOS 9 的新功能 universal links
- QuartZ2D
- html按钮打开某些apps,如果没有则打开应用商店时ios中遇到的问题
- iOS 动态改变约束
- iOS字体根据不同屏幕尺寸适配
- SDWebImage支持URL不变时更新图片内容
- iOS7下 -[XXX layoutSublayersOfLayer:]错误
- iOS 崩溃信息拦截防止闪退
- iOS CoreAnimation专题——原理篇(四)动画时间控制
- iOS开发拓展篇—CoreLocation定位服务
- ios一步一步编译ffmpeg,x264实现h264编码
- iOS 内存泄漏整理
- IOS开发-XCode常用快捷键整理