注:前些日子看到在http://www.apkbus.com/forum.php?mod=viewthread&tid=158139&extra=page%3D22的代码,感觉效果不错,遂向其学习而写如下代码,为其精简版,没有楼主的例子完美。以此记录,来记录学习历程,以备后用。
先上图:
在这写下自己的思路:
首先是个listview,但该listview的item左滑的时候,就会出现如图效果。想到应该是自定义的listview,复写其OnTouchEvent方法。那每个listview的item的滑动又是怎么实现的呢?是的,您猜的没错,用的是scroller。
listitem的每个item的xml:
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" <LinearLayout android:id="@+id/view_content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > </LinearLayout> <RelativeLayout android:id="@+id/holder" android:layout_width="120dp" android:layout_height="match_parent" android:clickable="true" android:background="@drawable/holder_bg"> <TextView android:id="@+id/delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/del_icon_normal" android:layout_centerInParent="true" android:gravity="center" android:textColor="@color/floralwhite" android:text="删除" /> </RelativeLayout> </merge>
slideview类:
package com.ryg.slideview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Scroller; import android.widget.TextView; public class SlideView extends LinearLayout { private static final String TAG = "SlideView"; private Context mContext; private LinearLayout mViewContent; private RelativeLayout mHolder; private Scroller mScroller; private int mHolderWidth = 120; private int mLastX = 0; private int mLastY = 0; private static final int TAN = 2; public SlideView(Context context) { super(context); initView(); } public SlideView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { mContext = getContext(); mScroller = new Scroller(mContext); setOrientation(LinearLayout.HORIZONTAL); View.inflate(mContext, R.layout.slide_view_merge, this); mViewContent = (LinearLayout) findViewById(R.id.view_content); mHolderWidth = Math.round(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources() .getDisplayMetrics())); // TypedValue.COMPLEX_UNIT_PX,时在不同手机上的数值都是一样的,还是原来数据120. // /* * mHolderWidth = Math.round(TypedValue.applyDimension( * TypedValue.COMPLEX_UNIT_PX, mHolderWidth, getResources() * .getDisplayMetrics())); */ // TypedValue.COMPLEX_UNIT_DIP在不同手机上显示的是不同的,是独立于设备的。 // 在公司e6机器上显示的是180,在lg上显示240 System.out.println("转化后的mHolderWidth is " + mHolderWidth); } public void setButtonText(CharSequence text) { ((TextView) findViewById(R.id.delete)).setText(text); } public void setContentView(View view) { mViewContent.addView(view); } public void onRequireTouchEvent(MotionEvent event) { // 注意执行顺序,每次不同的action都要执行int x=event.getX();和mLastX=x; // 注意此处的event。getX.越靠左的点x坐标越小,越靠右,x的坐标越大。 int x = (int) event.getX(); int y = (int) event.getY(); System.out.println("event.getX is " + x + "event.getY is --" + y); // 该处方法是获得滑动了多少距离,根据打印的log。当滑动了180时就不再滑动了 int scrollX = getScrollX(); System.out.println("滑动了多少距离" + scrollX); Log.d(TAG, "x=" + x + " y=" + y); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("----------down down down down "); break; case MotionEvent.ACTION_MOVE: System.out.println("-----------move move move "); int deltaX = x - mLastX; int deltaY = y - mLastY; System.out.println("----move deltaX is" + deltaX); if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) { break; } // 注意这一步的处理,使用的减号 int newScrollX = scrollX - deltaX; System.out.println("--------newScroll is" + newScrollX); if (deltaX != 0) { // 此处为如果复原向右滑则滑动到初始状态,否则滑动到最左 if (newScrollX < 0) { newScrollX = 0; } else if (newScrollX > mHolderWidth) { newScrollX = mHolderWidth; } // scrollTo的参数x,若为负数则向右滚动,若为正数则向左滚动 this.scrollTo(newScrollX, 0); } break; case MotionEvent.ACTION_UP: System.out.println("------------up"); newScrollX = 0; // 如果已经滑动le0.75倍的距离,则直接滑动到目的地,否则滑动回原来的位置 if (scrollX - mHolderWidth * 0.75 > 0) { newScrollX = mHolderWidth; } this.smoothScrollTo(newScrollX, 0); break; default: break; } mLastX = x; mLastY = y; System.out.println("---------last x -----" + mLastX); } private void smoothScrollTo(int destX, int destY) { // 缓慢滚动到指定位置 // 返回滚动的view的左边界 int scrollX = getScrollX(); // 在该例子中,当向左滑动时此处的scrollX是正数 System.out.println("scrollX is" + scrollX); // getScrollX是得到总共滑动的距离,必定为正数 int delta = destX - scrollX; // startScroll中的参数xofferset如果为正数则向左滑动,yofferset如果为正数则向上滑动 mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } } 现在可以看下listview的适配器中每个item的视图是怎么组织的 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; SlideView slideView = (SlideView) convertView; if (slideView == null) { View itemView = mInflater.inflate(R.layout.list_item, null); slideView = new SlideView(MainActivity.this); slideView.setContentView(itemView); holder = new ViewHolder(slideView); // slideView.setOnSlideListener(MainActivity.this); slideView.setTag(holder); } else { holder = (ViewHolder) slideView.getTag(); } MessageItem item = mMessageItems.get(position); item.slideView = slideView; holder.icon.setImageResource(item.iconRes); holder.title.setText(item.title); holder.msg.setText(item.msg); holder.time.setText(item.time); holder.deleteHolder.setOnClickListener(MainActivity.this); return slideView; }
为什么merge标签会有这种效果呢,还是不是很明白。如果将merge标签换为framelayout则不会有这种视图效果。疑问中。
菜鸟帖子,勿喷。
源码地址:http://download.csdn.net/detail/u010095768/7186465