android中画虚线–.PathEffect类简单认识

Java代码 <embed src="http://androidbin.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash" width="14" height="15"> </embed> <a title="收藏这段代码">![收藏代码](http://androidbin.iteye.com/images/icon_star.png)</a> </div> - Paint p = <span class="keyword">new</span> Paint(Paint.ANTI_ALIAS_FLAG); - p.setStyle(Style.STROKE); - p.setColor(Color.WHITE); - p.setStrokeWidth(<span class="number">1</span>); - PathEffect effects = <span class="keyword">new</span> DashPathEffect(<span class="keyword">new</span> <span class="keyword">float</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">8</span>}, <span class="number">1</span>); - p.setPathEffect(effects); - canvas.drawLine(<span class="number"></span>, <span class="number">40</span>, mWidth, <span class="number">40</span>, p); DashPathEffect是PathEffect类的一个子类,可以使paint画出类似虚线的样子,并且可以任意指定虚实的排列方式. 代码中的float数组,必须是偶数长度,且>=2,指定了多少长度的实线之后再画多少长度的空白. 如本代码中,绘制长度1的实线,再绘制长度2的空白,再绘制长度4的实线,再绘制长度8的空白,依次重复.1是偏移量,可以不用理会. 效果如下: 简单介绍下 PathEffect类: PathEffect是用来控制绘制轮廓(线条)的方式。 PathEffect对于绘制Path基本图形特别有用,但是它们也可以应用到任何Paint中从而影响线条绘制的方式。 使用PathEffect,可以改变一个形状的边角的外观并且控制轮廓的外表。 Android包含了多个PathEffect,包括: CornerPathEffect 可以使用圆角来代替尖锐的角从而对基本图形的形状尖锐的边角进行平滑。 ...

2015年3月22日 · 1 分钟 · 天边的星星

工程带有Fastjson或Gson等的第三方包的混淆配置

转自: http://blog.csdn.net/taotao19880301/article/details/17119249 工程中使用了fastjson,无奈,对工程做混淆的时候总是报错过不去,后来过去了又出现使用fastjson的地方数据不正确的问题,试了好多办法才成功,废话不多说,添加的代码: [view plain](http://www.programgo.com/article/6267404252/#) - ##&#8212;&#8212;&#8212;&#8212;&#8212;Begin: proguard configuration <span class="keyword">for</span> fastjson &#8212;&#8212;&#8212;- - - #-keepnames <span class="keyword">class</span> * <span class="keyword">implements</span> java.io.Serializable - -keep <span class="keyword">public</span> <span class="keyword">class</span> * <span class="keyword">implements</span> java.io.Serializable { - <span class="keyword">public</span> *; - } - -keepclassmembers <span class="keyword">class</span> * <span class="keyword">implements</span> java.io.Serializable { - <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">long</span> serialVersionUID; - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> java.io.ObjectStreamField[] serialPersistentFields; - <span class="keyword">private</span> <span class="keyword">void</span> writeObject(java.io.ObjectOutputStream); - <span class="keyword">private</span> <span class="keyword">void</span> readObject(java.io.ObjectInputStream); - java.lang.Object writeReplace(); - java.lang.Object readResolve(); - } - -dontwarn android.support.** - -dontwarn com.alibaba.fastjson.** - - -dontskipnonpubliclibraryclassmembers - -dontskipnonpubliclibraryclasses - - -libraryjars libs/fastjson.jar - -keep <span class="keyword">class</span> com.alibaba.fastjson.** { *; } - - -keepclassmembers <span class="keyword">class</span> * { - <span class="keyword">public</span> <methods>; - } - - ##&#8212;&#8212;&#8212;&#8212;&#8212;End: proguard configuration <span class="keyword">for</span> fastjson &#8212;&#8212;&#8212;- Gson的混淆: ...

2015年3月17日 · 2 分钟 · 天边的星星

Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8689140 大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话。 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多高手喜欢把自己的经验写在网上,供大家来学习,我也是从中受惠了很多,在此我深表感谢。可是我发现我却从来没有将自己平时的一些心得拿出来与大家分享,共同学习,太没有奉献精神了。于是我痛定思痛,决定从今天开始写博客,希望可以指点在我后面的开发者,更快地进入Android开发者的行列当中。 好了,废话就说这么多,下面开始进入今天的主题吧。 360手机卫士我相信大家都知道,好多人手机上都会装这一款软件,那么我们对它的一个桌面悬浮窗效果想必都不会陌生。请看下图: 首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速。好,我们现在就来模拟实现一下类似的效果。 先谈一下基本的实现原理,这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多。主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗。其中悬浮窗的参数有必要详细说明一下。 WindowManager.LayoutParams这个类用于提供悬浮窗所需的参数,其中有几个经常会用到的变量: type值用于确定悬浮窗的类型,一般设为2002,表示在所有应用程序之上,但在状态栏之下。 flags值用于确定悬浮窗的行为,比如说不可聚焦,非模态对话框等等,属性非常多,大家可以查看文档。 gravity值用于确定悬浮窗的对齐方式,一般设为左上角对齐,这样当拖动悬浮窗的时候方便计算坐标。 x值用于确定悬浮窗的位置,如果要横向移动悬浮窗,就需要改变这个值。 y值用于确定悬浮窗的位置,如果要纵向移动悬浮窗,就需要改变这个值。 width值用于指定悬浮窗的宽度。 height值用于指定悬浮窗的高度。 创建悬浮窗这种窗体需要向用户申请权限才可以的,因此还需要在AndroidManifest.xml中加入 原理介绍完了,下面我们开始用代码实现。首先在Eclipse中新建一个Android项目,项目名就叫做360FloatWindowDemo。然后写一下布局文件,布局文件非常简单,只有一个按钮,打开或新建activity_main.xml,加入如下代码: **[html]** [view plain](http://blog.csdn.net/guolin_blog/article/details/8689140#)[copy](http://blog.csdn.net/guolin_blog/article/details/8689140#) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span> - <span class="attribute">tools:context</span>=<span class="attribute-value">&#8220;.MainActivity&#8221;</span> <span class="tag">></span> - <span class="tag"><</span><span class="tag-name">Button</span> - <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/start_float_window&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;Start Float Window&#8221;</span> <span class="tag">></span> - <span class="tag"></</span><span class="tag-name">Button</span><span class="tag">></span> - <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span> 然后再新建一个名为float_window_small.xml的布局文件,用于做为小悬浮窗的布局,在其中加入如下代码: ...

2015年3月9日 · 13 分钟 · 天边的星星

Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换

转帖(http://blog.csdn.net/xiaanming/article/details/17718579) 在Android开发中,我们常常用到ListView和GridView,而有的时候系统的ListView,GridView并不能满足我们的需求,所以我们需要自己定义一个ListView或者GridView,我的上一篇文章中就是自定义的一个左右滑动删除item的例子,大家有兴趣的可以去看看 Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,今天这篇文章就给大家来自定义GridView的控件,GridView主要是来显示网格的控件,在Android的开发中使用很普通,相对于TextView,Button这些控件来说要来的复杂些,今天给大家带来长按GridView的item,然后将其拖拽其他item上面,使得GridView的item发生交换,比较典型的就是我们的Launcher,网上有很多关于GridView的拖动的Demo,但是大部分都是相同的,而且存在一些Bug,而且大部分都是点击GridView的item然后进行拖动,或者item之间不进行实时交换,今天给大家更加详细的介绍GridView拖拽,并且将Demo做的更完美,大家更容易接受,也许很多人听到这个感觉实现起来很复杂,就关掉的这篇文章,其实告诉大家,只要知道了思路就感觉一点都不复杂了,不信大家可以接着往下看看,首先还是跟大家说说实现的思路 根据手指按下的X,Y坐标来获取我们在GridView上面点击的item 手指按下的时候使用Handler和Runnable来实现一个定时器,假如定时时间为1000毫秒,在1000毫秒内,如果手指抬起了移除定时器,没有抬起并且手指点击在GridView的item所在的区域,则表示我们长按了GridView的item 如果我们长按了item则隐藏item,然后使用WindowManager来添加一个item的镜像在屏幕用来代替刚刚隐藏的item 当我们手指在屏幕移动的时候,更新item镜像的位置,然后在根据我们移动的X,Y的坐标来获取移动到GridView的哪一个位置 到GridView的item过多的时候,可能一屏幕显示不完,我们手指拖动item镜像到屏幕下方,要触发GridView想上滚动,同理,当我们手指拖动item镜像到屏幕上面,触发GridView向下滚动 GridView交换数据,刷新界面,移除item的镜像 看完上面的这些思路你是不是找到了些感觉了呢,心里痒痒的想动手试试吧,好吧,接下来就带大家根据思路来实现可拖拽的GridView,新建一个项目就叫DragGridView 新建一个类DragGridView继承GridView,先来看看DragGridView的代码,然后在根据代码进行相关的讲解 **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/17718579#)[copy](http://blog.csdn.net/xiaanming/article/details/17718579#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/143802)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/143802/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.draggridview; - - <span class="keyword">import</span> android.app.Activity; - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.graphics.Bitmap; - <span class="keyword">import</span> android.graphics.PixelFormat; - <span class="keyword">import</span> android.graphics.Rect; - <span class="keyword">import</span> android.os.Handler; - <span class="keyword">import</span> android.os.Vibrator; - <span class="keyword">import</span> android.util.AttributeSet; - <span class="keyword">import</span> android.view.Gravity; - <span class="keyword">import</span> android.view.MotionEvent; - <span class="keyword">import</span> android.view.View; - <span class="keyword">import</span> android.view.WindowManager; - <span class="keyword">import</span> android.widget.AdapterView; - <span class="keyword">import</span> android.widget.GridView; - <span class="keyword">import</span> android.widget.ImageView; - - <span class="comment">/**</span> - <span class="comment"> * @blog http://blog.csdn.net/xiaanming </span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> DragGridView <span class="keyword">extends</span> GridView{ - <span class="comment">/**</span> - <span class="comment"> * DragGridView的item长按响应的时间, 默认是1000毫秒,也可以自行设置</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">long</span> dragResponseMS = <span class="number">1000</span>; - - <span class="comment">/**</span> - <span class="comment"> * 是否可以拖拽,默认不可以</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> isDrag = <span class="keyword">false</span>; - - <span class="keyword">private</span> <span class="keyword">int</span> mDownX; - <span class="keyword">private</span> <span class="keyword">int</span> mDownY; - <span class="keyword">private</span> <span class="keyword">int</span> moveX; - <span class="keyword">private</span> <span class="keyword">int</span> moveY; - <span class="comment">/**</span> - <span class="comment"> * 正在拖拽的position</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mDragPosition; - - <span class="comment">/**</span> - <span class="comment"> * 刚开始拖拽的item对应的View</span> - <span class="comment"> */</span> - <span class="keyword">private</span> View mStartDragItemView = <span class="keyword">null</span>; - - <span class="comment">/**</span> - <span class="comment"> * 用于拖拽的镜像,这里直接用一个ImageView</span> - <span class="comment"> */</span> - <span class="keyword">private</span> ImageView mDragImageView; - - <span class="comment">/**</span> - <span class="comment"> * 震动器</span> - <span class="comment"> */</span> - <span class="keyword">private</span> Vibrator mVibrator; - - <span class="keyword">private</span> WindowManager mWindowManager; - <span class="comment">/**</span> - <span class="comment"> * item镜像的布局参数</span> - <span class="comment"> */</span> - <span class="keyword">private</span> WindowManager.LayoutParams mWindowLayoutParams; - - <span class="comment">/**</span> - <span class="comment"> * 我们拖拽的item对应的Bitmap</span> - <span class="comment"> */</span> - <span class="keyword">private</span> Bitmap mDragBitmap; - - <span class="comment">/**</span> - <span class="comment"> * 按下的点到所在item的上边缘的距离</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mPoint2ItemTop ; - - <span class="comment">/**</span> - <span class="comment"> * 按下的点到所在item的左边缘的距离</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mPoint2ItemLeft; - - <span class="comment">/**</span> - <span class="comment"> * DragGridView距离屏幕顶部的偏移量</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mOffset2Top; - - <span class="comment">/**</span> - <span class="comment"> * DragGridView距离屏幕左边的偏移量</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mOffset2Left; - - <span class="comment">/**</span> - <span class="comment"> * 状态栏的高度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mStatusHeight; - - <span class="comment">/**</span> - <span class="comment"> * DragGridView自动向下滚动的边界值</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mDownScrollBorder; - - <span class="comment">/**</span> - <span class="comment"> * DragGridView自动向上滚动的边界值</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mUpScrollBorder; - - <span class="comment">/**</span> - <span class="comment"> * DragGridView自动滚动的速度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> speed = <span class="number">20</span>; - - <span class="comment">/**</span> - <span class="comment"> * item发生变化回调的接口</span> - <span class="comment"> */</span> - <span class="keyword">private</span> OnChanageListener onChanageListener; - - - - <span class="keyword">public</span> DragGridView(Context context) { - <span class="keyword">this</span>(context, <span class="keyword">null</span>); - } - - <span class="keyword">public</span> DragGridView(Context context, AttributeSet attrs) { - <span class="keyword">this</span>(context, attrs, <span class="number"></span>); - } - - <span class="keyword">public</span> DragGridView(Context context, AttributeSet attrs, <span class="keyword">int</span> defStyle) { - <span class="keyword">super</span>(context, attrs, defStyle); - mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - mStatusHeight = getStatusHeight(context); <span class="comment">//获取状态栏的高度</span> - - } - - <span class="keyword">private</span> Handler mHandler = <span class="keyword">new</span> Handler(); - - <span class="comment">//用来处理是否为长按的Runnable</span> - <span class="keyword">private</span> Runnable mLongClickRunnable = <span class="keyword">new</span> Runnable() { - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> run() { - isDrag = <span class="keyword">true</span>; <span class="comment">//设置可以拖拽</span> - mVibrator.vibrate(<span class="number">50</span>); <span class="comment">//震动一下</span> - mStartDragItemView.setVisibility(View.INVISIBLE);<span class="comment">//隐藏该item</span> - - <span class="comment">//根据我们按下的点显示item镜像</span> - createDragImage(mDragBitmap, mDownX, mDownY); - } - }; - - <span class="comment">/**</span> - <span class="comment"> * 设置回调接口</span> - <span class="comment"> * @param onChanageListener</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setOnChangeListener(OnChanageListener onChanageListener){ - <span class="keyword">this</span>.onChanageListener = onChanageListener; - } - - <span class="comment">/**</span> - <span class="comment"> * 设置响应拖拽的毫秒数,默认是1000毫秒</span> - <span class="comment"> * @param dragResponseMS</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setDragResponseMS(<span class="keyword">long</span> dragResponseMS) { - <span class="keyword">this</span>.dragResponseMS = dragResponseMS; - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">boolean</span> dispatchTouchEvent(MotionEvent ev) { - <span class="keyword">switch</span>(ev.getAction()){ - <span class="keyword">case</span> MotionEvent.ACTION_DOWN: - mDownX = (<span class="keyword">int</span>) ev.getX(); - mDownY = (<span class="keyword">int</span>) ev.getY(); - - <span class="comment">//根据按下的X,Y坐标获取所点击item的position</span> - mDragPosition = pointToPosition(mDownX, mDownY); - - - <span class="keyword">if</span>(mDragPosition == AdapterView.INVALID_POSITION){ - <span class="keyword">return</span> <span class="keyword">super</span>.dispatchTouchEvent(ev); - } - - <span class="comment">//使用Handler延迟dragResponseMS执行mLongClickRunnable</span> - mHandler.postDelayed(mLongClickRunnable, dragResponseMS); - - <span class="comment">//根据position获取该item所对应的View</span> - mStartDragItemView = getChildAt(mDragPosition &#8211; getFirstVisiblePosition()); - - <span class="comment">//下面这几个距离大家可以参考我的博客上面的图来理解下</span> - mPoint2ItemTop = mDownY &#8211; mStartDragItemView.getTop(); - mPoint2ItemLeft = mDownX &#8211; mStartDragItemView.getLeft(); - - mOffset2Top = (<span class="keyword">int</span>) (ev.getRawY() &#8211; mDownY); - mOffset2Left = (<span class="keyword">int</span>) (ev.getRawX() &#8211; mDownX); - - <span class="comment">//获取DragGridView自动向上滚动的偏移量,小于这个值,DragGridView向下滚动</span> - mDownScrollBorder = getHeight() /<span class="number">4</span>; - <span class="comment">//获取DragGridView自动向下滚动的偏移量,大于这个值,DragGridView向上滚动</span> - mUpScrollBorder = getHeight() * <span class="number">3</span>/<span class="number">4</span>; - - - - <span class="comment">//开启mDragItemView绘图缓存</span> - mStartDragItemView.setDrawingCacheEnabled(<span class="keyword">true</span>); - <span class="comment">//获取mDragItemView在缓存中的Bitmap对象</span> - mDragBitmap = Bitmap.createBitmap(mStartDragItemView.getDrawingCache()); - <span class="comment">//这一步很关键,释放绘图缓存,避免出现重复的镜像</span> - mStartDragItemView.destroyDrawingCache(); - - - <span class="keyword">break</span>; - <span class="keyword">case</span> MotionEvent.ACTION_MOVE: - <span class="keyword">int</span> moveX = (<span class="keyword">int</span>)ev.getX(); - <span class="keyword">int</span> moveY = (<span class="keyword">int</span>) ev.getY(); - - <span class="comment">//如果我们在按下的item上面移动,只要不超过item的边界我们就不移除mRunnable</span> - <span class="keyword">if</span>(!isTouchInItem(mStartDragItemView, moveX, moveY)){ - mHandler.removeCallbacks(mLongClickRunnable); - } - <span class="keyword">break</span>; - <span class="keyword">case</span> MotionEvent.ACTION_UP: - mHandler.removeCallbacks(mLongClickRunnable); - mHandler.removeCallbacks(mScrollRunnable); - <span class="keyword">break</span>; - } - <span class="keyword">return</span> <span class="keyword">super</span>.dispatchTouchEvent(ev); - } - - - <span class="comment">/**</span> - <span class="comment"> * 是否点击在GridView的item上面</span> - <span class="comment"> * @param itemView</span> - <span class="comment"> * @param x</span> - <span class="comment"> * @param y</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> isTouchInItem(View dragView, <span class="keyword">int</span> x, <span class="keyword">int</span> y){ - <span class="keyword">if</span>(dragView == <span class="keyword">null</span>){ - <span class="keyword">return</span> <span class="keyword">false</span>; - } - <span class="keyword">int</span> leftOffset = dragView.getLeft(); - <span class="keyword">int</span> topOffset = dragView.getTop(); - <span class="keyword">if</span>(x < leftOffset || x > leftOffset + dragView.getWidth()){ - <span class="keyword">return</span> <span class="keyword">false</span>; - } - - <span class="keyword">if</span>(y < topOffset || y > topOffset + dragView.getHeight()){ - <span class="keyword">return</span> <span class="keyword">false</span>; - } - - <span class="keyword">return</span> <span class="keyword">true</span>; - } - - - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">boolean</span> onTouchEvent(MotionEvent ev) { - <span class="keyword">if</span>(isDrag && mDragImageView != <span class="keyword">null</span>){ - <span class="keyword">switch</span>(ev.getAction()){ - <span class="keyword">case</span> MotionEvent.ACTION_MOVE: - moveX = (<span class="keyword">int</span>) ev.getX(); - moveY = (<span class="keyword">int</span>) ev.getY(); - <span class="comment">//拖动item</span> - onDragItem(moveX, moveY); - <span class="keyword">break</span>; - <span class="keyword">case</span> MotionEvent.ACTION_UP: - onStopDrag(); - isDrag = <span class="keyword">false</span>; - <span class="keyword">break</span>; - } - <span class="keyword">return</span> <span class="keyword">true</span>; - } - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - } - - - <span class="comment">/**</span> - <span class="comment"> * 创建拖动的镜像</span> - <span class="comment"> * @param bitmap </span> - <span class="comment"> * @param downX</span> - <span class="comment"> * 按下的点相对父控件的X坐标</span> - <span class="comment"> * @param downY</span> - <span class="comment"> * 按下的点相对父控件的X坐标</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> createDragImage(Bitmap bitmap, <span class="keyword">int</span> downX , <span class="keyword">int</span> downY){ - mWindowLayoutParams = <span class="keyword">new</span> WindowManager.LayoutParams(); - mWindowLayoutParams.format = PixelFormat.TRANSLUCENT; <span class="comment">//图片之外的其他地方透明</span> - mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; - mWindowLayoutParams.x = downX &#8211; mPoint2ItemLeft + mOffset2Left; - mWindowLayoutParams.y = downY &#8211; mPoint2ItemTop + mOffset2Top &#8211; mStatusHeight; - mWindowLayoutParams.alpha = <span class="number"></span>.55f; <span class="comment">//透明度</span> - mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; - mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE ; - - mDragImageView = <span class="keyword">new</span> ImageView(getContext()); - mDragImageView.setImageBitmap(bitmap); - mWindowManager.addView(mDragImageView, mWindowLayoutParams); - } - - <span class="comment">/**</span> - <span class="comment"> * 从界面上面移动拖动镜像</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> removeDragImage(){ - <span class="keyword">if</span>(mDragImageView != <span class="keyword">null</span>){ - mWindowManager.removeView(mDragImageView); - mDragImageView = <span class="keyword">null</span>; - } - } - - <span class="comment">/**</span> - <span class="comment"> * 拖动item,在里面实现了item镜像的位置更新,item的相互交换以及GridView的自行滚动</span> - <span class="comment"> * @param x</span> - <span class="comment"> * @param y</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> onDragItem(<span class="keyword">int</span> moveX, <span class="keyword">int</span> moveY){ - mWindowLayoutParams.x = moveX &#8211; mPoint2ItemLeft + mOffset2Left; - mWindowLayoutParams.y = moveY &#8211; mPoint2ItemTop + mOffset2Top &#8211; mStatusHeight; - mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams); <span class="comment">//更新镜像的位置</span> - onSwapItem(moveX, moveY); - - <span class="comment">//GridView自动滚动</span> - mHandler.post(mScrollRunnable); - } - - - <span class="comment">/**</span> - <span class="comment"> * 当moveY的值大于向上滚动的边界值,触发GridView自动向上滚动</span> - <span class="comment"> * 当moveY的值小于向下滚动的边界值,触犯GridView自动向下滚动</span> - <span class="comment"> * 否则不进行滚动</span> - <span class="comment"> */</span> - <span class="keyword">private</span> Runnable mScrollRunnable = <span class="keyword">new</span> Runnable() { - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> run() { - <span class="keyword">int</span> scrollY; - <span class="keyword">if</span>(moveY > mUpScrollBorder){ - scrollY = speed; - mHandler.postDelayed(mScrollRunnable, <span class="number">25</span>); - }<span class="keyword">else</span> <span class="keyword">if</span>(moveY < mDownScrollBorder){ - scrollY = -speed; - mHandler.postDelayed(mScrollRunnable, <span class="number">25</span>); - }<span class="keyword">else</span>{ - scrollY = <span class="number"></span>; - mHandler.removeCallbacks(mScrollRunnable); - } - - <span class="comment">//当我们的手指到达GridView向上或者向下滚动的偏移量的时候,可能我们手指没有移动,但是DragGridView在自动的滚动</span> - <span class="comment">//所以我们在这里调用下onSwapItem()方法来交换item</span> - onSwapItem(moveX, moveY); - - - smoothScrollBy(scrollY, <span class="number">10</span>); - } - }; - - - <span class="comment">/**</span> - <span class="comment"> * 交换item,并且控制item之间的显示与隐藏效果</span> - <span class="comment"> * @param moveX</span> - <span class="comment"> * @param moveY</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> onSwapItem(<span class="keyword">int</span> moveX, <span class="keyword">int</span> moveY){ - <span class="comment">//获取我们手指移动到的那个item的position</span> - <span class="keyword">int</span> tempPosition = pointToPosition(moveX, moveY); - - <span class="comment">//假如tempPosition 改变了并且tempPosition不等于-1,则进行交换</span> - <span class="keyword">if</span>(tempPosition != mDragPosition && tempPosition != AdapterView.INVALID_POSITION){ - <span class="keyword">if</span>(onChanageListener != <span class="keyword">null</span>){ - onChanageListener.onChange(mDragPosition, tempPosition); - } - - getChildAt(tempPosition &#8211; getFirstVisiblePosition()).setVisibility(View.INVISIBLE);<span class="comment">//拖动到了新的item,新的item隐藏掉</span> - getChildAt(mDragPosition &#8211; getFirstVisiblePosition()).setVisibility(View.VISIBLE);<span class="comment">//之前的item显示出来</span> - - mDragPosition = tempPosition; - } - } - - - <span class="comment">/**</span> - <span class="comment"> * 停止拖拽我们将之前隐藏的item显示出来,并将镜像移除</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> onStopDrag(){ - View view = getChildAt(mDragPosition &#8211; getFirstVisiblePosition()); - <span class="keyword">if</span>(view != <span class="keyword">null</span>){ - view.setVisibility(View.VISIBLE); - } - ((DragAdapter)<span class="keyword">this</span>.getAdapter()).setItemHide(-<span class="number">1</span>); - removeDragImage(); - } - - <span class="comment">/**</span> - <span class="comment"> * 获取状态栏的高度</span> - <span class="comment"> * @param context</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> getStatusHeight(Context context){ - <span class="keyword">int</span> statusHeight = <span class="number"></span>; - Rect localRect = <span class="keyword">new</span> Rect(); - ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); - statusHeight = localRect.top; - <span class="keyword">if</span> (<span class="number"></span> == statusHeight){ - Class<?> localClass; - <span class="keyword">try</span> { - localClass = Class.forName(<span class="string">&#8220;com.android.internal.R$dimen&#8221;</span>); - Object localObject = localClass.newInstance(); - <span class="keyword">int</span> i5 = Integer.parseInt(localClass.getField(<span class="string">&#8220;status_bar_height&#8221;</span>).get(localObject).toString()); - statusHeight = context.getResources().getDimensionPixelSize(i5); - } <span class="keyword">catch</span> (Exception e) { - e.printStackTrace(); - } - } - <span class="keyword">return</span> statusHeight; - } - - - <span class="comment">/**</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">interface</span> OnChanageListener{ - - <span class="comment">/**</span> - <span class="comment"> * 当item交换位置的时候回调的方法,我们只需要在该方法中实现数据的交换即可</span> - <span class="comment"> * @param form</span> - <span class="comment"> * 开始的position</span> - <span class="comment"> * @param to </span> - <span class="comment"> * 拖拽到的position</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> onChange(<span class="keyword">int</span> form, <span class="keyword">int</span> to); - } - } 首先看DragGridView的事件分发方法,不了解Android事件分发的可以先去了解下,Android事件分发对于自定义控件很重要,简单说下,当我们点击DragGridView的Item,先会去执行dispatchTouchEvent()方法将事件分发下去,所以我们要重写dispatchTouchEvent()方法在手指按下的时候根据pointToPosition()方法来获取我们按下的item的position,根据getChildAt()方法来获取该position上面所对应的View, 并且开启长按的定时器,默认时间为1000毫秒,如果在1000毫秒内手指抬起或者手指在屏幕上滑动出了该item,则取消长按定时器,否则就表示可以进行拖拽,手机友好的震动一下,隐藏我们长按的Item,屏幕调用createDragImage()方法来创建我们长按的item的镜像,创建Item的镜像使用的是WindowManager类,该类可以创建一个窗体显示在Activity之上,再此之前大家先要理解这几个距离,理解这几个距离之前要首先知道getRawX(),getRawY()和getX(),getY()的区别,getRawX(),getRawY()是相对于屏幕的原点的距离,而getX(),getY()是相对于控件左上方的点的距离,为了方便大家理解我用Word简单的画了下图,画得不好,大家将就的看下,红色框框为我们的GridView ...

2015年3月7日 · 12 分钟 · 天边的星星

Android 向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果

转载(http://blog.csdn.net/xiaanming/article/details/20934541) 今天给大家带来一个向右滑动销毁Activity的效果,Activtiy随着手指的移动而移动,该效果在Android应用中还是比较少见的,在IOS中就比较常见了,例如“网易新闻” ,”美食杰” , “淘宝”等应用采用此效果,而Android应用中“知乎”采用的也是这种滑动切换Activity的效果, 不过我发现“淘宝”并没有随着手势的移动而移动,只是捕捉到滑动手势,然后产生平滑切换界面的动画效果,这个在Android中还是很好实现的, 网上很多滑动切换Activity的Demo貌似都是这种效果的吧,如果要实现类似“网易新闻”的随手势的滑动而滑动,似乎就要复杂一些了,我之前在IOS中看到”网易新闻”的这种效果就很感兴趣,然后群里也有朋友问我怎么实现类似“知乎”这个应用的滑动切换的效果,我也特意去下了一个“知乎”,在之前的实现中我遇到了一些瓶颈,没有实现出来就搁置了在那里,今天无意中看到给Activity设置透明的背景,于是乎我恍然大悟,真是灵感来源于瞬间,不能强求啊,然后自己就将此效果实现了出来,给大家分享一下,希望给有此需求的你一点点帮助。 不知道大家对Scroller这个类以及View的scrollBy() 和scrollTo()的使用熟悉不?我之前介绍了Scroller类的滑动实现原理Android 带你从源码的角度解析Scroller的滚动实现原理,在那里面也介绍了scrollBy() 和scrollTo()方法,不明白的同学可以去看看,这对实现此效果有很大的帮助,了解scrollBy() 和scrollTo()的朋友应该知道,如果想对某个View(例如Button)就行滚动,我们直接调用该View(Button)的scrollBy()方法,并不是该View(Button)进行滚动,而是该View里面的内容(Button上面的文字)进行滚动,所以我们假如要让View整体滚动就需要对其View的父布局调用scrollBy()方法,回到这篇文章来,假如我们想要对一个Activity进行滚动,我们就需求对这个Activity布局文件的顶层布局的父布局进行滚动 例如下面的XML布局文件 **[html]** [view plain](http://blog.csdn.net/xiaanming/article/details/20934541#)[copy](http://blog.csdn.net/xiaanming/article/details/20934541#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/232806)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/232806/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="tag"><</span><span class="tag-name">LinearLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:gravity</span>=<span class="attribute-value">&#8220;center&#8221;</span> - <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span> <span class="tag">></span> - - - <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span> 如果我们对LinearLayout进行滚动,并不能实现我们想要的效果,而只能对LinearLayout里面的内容或者说是子View进行滚动,所以我们需要获取利用LinearLayout的getParent()方法获取父布局,其实Android系统会对我们的布局文件的最外层套一个FrameLayout,所以我们其实就是对FrameLayout进行滚动就行了 了解了实现的原理之后,我们就来编写代码吧,首先新建一个android工程,取名SildingFinish ...

2015年3月7日 · 9 分钟 · 天边的星星

Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果

转载(http://blog.csdn.net/xiaanming/article/details/20481185) 大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSDN上面更新我的博客,欢迎大家关注一下,今天这篇文章主要的是介绍下开源库StickyGridHeaders的使用,StickyGridHeaders是一个自定义GridView带sections和headers的Android库,sections就是GridView item之间的分隔,headers就是固定在GridView顶部的标题,类似一些Android手机联系人的效果,StickyGridHeaders的介绍在https://github.com/TonicArtos/StickyGridHeaders,与此对应也有一个相同效果的自定义ListView带sections和headers的开源库https://github.com/emilsjolander/StickyListHeaders,大家有兴趣的可以去看下,我这里介绍的是StickyGridHeaders的使用,我在Android应用方面看到使用StickyGridHeaders的不是很多,而是在Iphone上看到相册采用的是这种效果,于是我就使用StickyGridHeaders来仿照Iphone按照日期分隔显示本地图片 我们先新建一个Android项目StickyHeaderGridView,去https://github.com/TonicArtos/StickyGridHeaders下载开源库,为了方便浏览源码我直接将源码拷到我的工程中了 com.tonicartos.widget.stickygridheaders这个包就是我放StickyGridHeaders开源库的源码,com.example.stickyheadergridview这个包是我实现此功能的代码,类看起来还蛮多的,下面我就一一来介绍了 GridItem用来封装StickyGridHeadersGridView 每个Item的数据,里面有本地图片的路径,图片加入手机系统的时间和headerId **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20481185#)[copy](http://blog.csdn.net/xiaanming/article/details/20481185#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/220204)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/220204/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.stickyheadergridview; - <span class="comment">/**</span> - <span class="comment"> * @blog http://blog.csdn.net/xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> GridItem { - <span class="comment">/**</span> - <span class="comment"> * 图片的路径</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String path; - <span class="comment">/**</span> - <span class="comment"> * 图片加入手机中的时间,只取了年月日</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String time; - <span class="comment">/**</span> - <span class="comment"> * 每个Item对应的HeaderId</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> headerId; - - <span class="keyword">public</span> GridItem(String path, String time) { - <span class="keyword">super</span>(); - <span class="keyword">this</span>.path = path; - <span class="keyword">this</span>.time = time; - } - - <span class="keyword">public</span> String getPath() { - <span class="keyword">return</span> path; - } - <span class="keyword">public</span> <span class="keyword">void</span> setPath(String path) { - <span class="keyword">this</span>.path = path; - } - <span class="keyword">public</span> String getTime() { - <span class="keyword">return</span> time; - } - <span class="keyword">public</span> <span class="keyword">void</span> setTime(String time) { - <span class="keyword">this</span>.time = time; - } - - <span class="keyword">public</span> <span class="keyword">int</span> getHeaderId() { - <span class="keyword">return</span> headerId; - } - - <span class="keyword">public</span> <span class="keyword">void</span> setHeaderId(<span class="keyword">int</span> headerId) { - <span class="keyword">this</span>.headerId = headerId; - } - - - } 图片的路径path和图片加入的时间time 我们直接可以通过ContentProvider获取,但是headerId需要我们根据逻辑来生成。 ...

2015年3月7日 · 13 分钟 · 天边的星星

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

转载:http://blog.csdn.net/xiaanming/article/details/18730223 写这篇文章之前,先简单说几句,首先是先恭喜下自己获得了2013年的博客之星称号,很意外也很开心,自己是从2013年开始写博客,那时候也不知道怎么写,我从小就不喜欢写日记,作文什么的,所以刚开始都是贴代码,也没有人看,后面慢慢的,写的文章被推荐博客首页和CSDN首页(这里也要小小的感谢下小编MM),访问量逐渐的多了起来,有更多的人看我的文章,这也使自己有了继续写文章的动力,也希望我写的东西对大家有点帮助吧,在2014年我会继续在CSDN上面写博客,然后是感谢博客之星给我投票支持我的朋友们,谢谢你们支持我的每一票,最后就是2014春节马上就到了,提前祝福大家新年快乐,工作顺利,事事顺心! 回到主题,之前群里面有朋友问我,有没有关于本地图片选择的Demo,类似微信的效果,他说网上没有这方面的Demo,问我能不能写一篇关于这个效果的Demo,于是我研究了下微信的本地图片选择的Demo,自己仿照的写了下分享给大家,希望对以后有这样子需求的朋友有一点帮助吧,主要使用的是ContentProvider扫描手机中的图片,并用GridView将图片显示出来,关于GridView和ListView显示图片的问题,一直是一个很头疼的问题,因为我们手机的内存有限,手机给每个应用程序分配的内存也有限,所以图片多的情况下很容易伴随着OOM的发生,不过现在也有很多的开源的图片显示框架,对显示很多图片进行了优化,大家有兴趣的可以去了解了解,今天我的这篇文章使用的是LruCache这个类(之前写了一篇使用LruCache加载网络图片的Android 异步加载图片,使用LruCache和SD卡或手机缓存,效果非常的流畅)以及对图片进行相对应的裁剪,这样也可以尽量的避免OOM的发生,我们先看下微信的效果吧 接下来我们就来实现这些效果吧,首先我们新建一个项目,取名ImageScan 首先我们先看第一个界面吧,使用将手机中的图片扫描出来,然后根据图片的所在的文件夹将其分类出来,并显示所在文件夹里面的一张图片和文件夹中图片个数,我们根据界面元素(文件夹名, 文件夹图片个数,文件夹中的一张图片)使用一个实体对象ImageBean来封装这三个属性 **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/18730223#)[copy](http://blog.csdn.net/xiaanming/article/details/18730223#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/169891)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/169891/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.imagescan; - - <span class="comment">/**</span> - <span class="comment"> * GridView的每个item的数据对象</span> - <span class="comment"> * </span> - <span class="comment"> * @author len</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> ImageBean{ - <span class="comment">/**</span> - <span class="comment"> * 文件夹的第一张图片路径</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String topImagePath; - <span class="comment">/**</span> - <span class="comment"> * 文件夹名</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String folderName; - <span class="comment">/**</span> - <span class="comment"> * 文件夹中的图片数</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> imageCounts; - - <span class="keyword">public</span> String getTopImagePath() { - <span class="keyword">return</span> topImagePath; - } - <span class="keyword">public</span> <span class="keyword">void</span> setTopImagePath(String topImagePath) { - <span class="keyword">this</span>.topImagePath = topImagePath; - } - <span class="keyword">public</span> String getFolderName() { - <span class="keyword">return</span> folderName; - } - <span class="keyword">public</span> <span class="keyword">void</span> setFolderName(String folderName) { - <span class="keyword">this</span>.folderName = folderName; - } - <span class="keyword">public</span> <span class="keyword">int</span> getImageCounts() { - <span class="keyword">return</span> imageCounts; - } - <span class="keyword">public</span> <span class="keyword">void</span> setImageCounts(<span class="keyword">int</span> imageCounts) { - <span class="keyword">this</span>.imageCounts = imageCounts; - } - - } 接下来就是主界面的布局啦,上面的导航栏我没有加进去,只有下面的GridView,所以说主界面布局中只有一个GridView ...

2015年3月7日 · 17 分钟 · 天边的星星

Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

转载(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很棒,当我们滑动Item超过一半的时候,item的透明度就变成了0,我们就知道抬起手指的时候item就被删除了,当item的透明度不为0的时候,我们抬起手指Item会回到起始位置,这样我们就知道拖动到什么位置item会删除,什么位置Item不删除,用户体验更好了,还有一个效果,就是我们滑动删除了item的时候,ListView的其他item会出现向上或者向下滚动的效果,感觉效果很棒,所以在GitHub上面搜索了下,发现很多开源库都有这个效果,比如ListViewAnimations, android-swipelistview等等,我看了下实现原理,使用的是Jake Wharton的动画开源库NineOldAndroids,这个库究竟是干嘛的呢?在API3.0(Honeycomb), SDK新增了一个android.animation包,里面的类是实现动画效果相关的类,通过Honeycomb API,能够实现非常复杂的动画效果,但是如果开发者想在3.0以下使用这一套API, 则需要使用开源框架Nine Old Androids,在这个库中会根据我们运行的机器判断其SDK版本,如果是API3.0以上则使用Android自带的动画类,否则就使用Nine Old Androids库中,这是一个兼容库,接下来我们就来看看这个效果的具体实现吧 实现该效果的主要思路 先根据手指触摸的点来获取点击的是ListView的哪一个Item 当手指在屏幕上面滑动的时候,我们要使得Item跟随手指的滑动而滑动 当我们抬起手指的时候,我们根据滑动的距离或者手指在屏幕上面的速度来判断Item是滑出屏幕还是滑动至其实位置 Item滑出屏幕时,使ListView的其他item产生向上挤压或者向下挤压的效果 大致的思路这是这四步,其中的一些细节接下来我会一一为大家解答的,接下来我们就用代码来实现这种效果吧 首先我们新建一个工程,叫Swipedismisslistview,我们需要将Nine Old Androids这个库引入到工程,大家可以去https://github.com/JakeWharton/NineOldAndroids下载,可以使用Jar包,也可以使用工程库的形式引入到我们自己的工程,我们还需要自定义一个ListView,我们先看代码然后给大家讲解下具体的功能实现 **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/18311877#)[copy](http://blog.csdn.net/xiaanming/article/details/18311877#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/159353)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/159353/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.swipedismisslistview; - - <span class="keyword">import</span> <span class="keyword">static</span> com.nineoldandroids.view.ViewHelper.setAlpha; - <span class="keyword">import</span> <span class="keyword">static</span> com.nineoldandroids.view.ViewHelper.setTranslationX; - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.util.AttributeSet; - <span class="keyword">import</span> android.view.MotionEvent; - <span class="keyword">import</span> android.view.VelocityTracker; - <span class="keyword">import</span> android.view.View; - <span class="keyword">import</span> android.view.ViewConfiguration; - <span class="keyword">import</span> android.view.ViewGroup; - <span class="keyword">import</span> android.widget.AdapterView; - <span class="keyword">import</span> android.widget.ListView; - - <span class="keyword">import</span> com.nineoldandroids.animation.Animator; - <span class="keyword">import</span> com.nineoldandroids.animation.AnimatorListenerAdapter; - <span class="keyword">import</span> com.nineoldandroids.animation.ValueAnimator; - <span class="keyword">import</span> com.nineoldandroids.view.ViewHelper; - <span class="keyword">import</span> com.nineoldandroids.view.ViewPropertyAnimator; - <span class="comment">/**</span> - <span class="comment"> * @blog http://blog.csdn.net/xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> SwipeDismissListView <span class="keyword">extends</span> ListView { - <span class="comment">/**</span> - <span class="comment"> * 认为是用户滑动的最小距离</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mSlop; - <span class="comment">/**</span> - <span class="comment"> * 滑动的最小速度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mMinFlingVelocity; - <span class="comment">/**</span> - <span class="comment"> * 滑动的最大速度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mMaxFlingVelocity; - <span class="comment">/**</span> - <span class="comment"> * 执行动画的时间</span> - <span class="comment"> */</span> - <span class="keyword">protected</span> <span class="keyword">long</span> mAnimationTime = <span class="number">150</span>; - <span class="comment">/**</span> - <span class="comment"> * 用来标记用户是否正在滑动中</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> mSwiping; - <span class="comment">/**</span> - <span class="comment"> * 滑动速度检测类</span> - <span class="comment"> */</span> - <span class="keyword">private</span> VelocityTracker mVelocityTracker; - <span class="comment">/**</span> - <span class="comment"> * 手指按下的position</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mDownPosition; - <span class="comment">/**</span> - <span class="comment"> * 按下的item对应的View</span> - <span class="comment"> */</span> - <span class="keyword">private</span> View mDownView; - <span class="keyword">private</span> <span class="keyword">float</span> mDownX; - <span class="keyword">private</span> <span class="keyword">float</span> mDownY; - <span class="comment">/**</span> - <span class="comment"> * item的宽度</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> mViewWidth; - <span class="comment">/**</span> - <span class="comment"> * 当ListView的Item滑出界面回调的接口</span> - <span class="comment"> */</span> - <span class="keyword">private</span> OnDismissCallback onDismissCallback; - - <span class="comment">/**</span> - <span class="comment"> * 设置动画时间</span> - <span class="comment"> * </span> - <span class="comment"> * @param mAnimationTime</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setmAnimationTime(<span class="keyword">long</span> mAnimationTime) { - <span class="keyword">this</span>.mAnimationTime = mAnimationTime; - } - - <span class="comment">/**</span> - <span class="comment"> * 设置删除回调接口</span> - <span class="comment"> * </span> - <span class="comment"> * @param onDismissCallback</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">void</span> setOnDismissCallback(OnDismissCallback onDismissCallback) { - <span class="keyword">this</span>.onDismissCallback = onDismissCallback; - } - - <span class="keyword">public</span> SwipeDismissListView(Context context) { - <span class="keyword">this</span>(context, <span class="keyword">null</span>); - } - - <span class="keyword">public</span> SwipeDismissListView(Context context, AttributeSet attrs) { - <span class="keyword">this</span>(context, attrs, <span class="number"></span>); - } - - <span class="keyword">public</span> SwipeDismissListView(Context context, AttributeSet attrs, - <span class="keyword">int</span> defStyle) { - <span class="keyword">super</span>(context, attrs, defStyle); - - ViewConfiguration vc = ViewConfiguration.get(context); - mSlop = vc.getScaledTouchSlop(); - mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * <span class="number">8</span>; <span class="comment">//获取滑动的最小速度</span> - mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); <span class="comment">//获取滑动的最大速度</span> - } - - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">boolean</span> onTouchEvent(MotionEvent ev) { - <span class="keyword">switch</span> (ev.getAction()) { - <span class="keyword">case</span> MotionEvent.ACTION_DOWN: - handleActionDown(ev); - <span class="keyword">break</span>; - <span class="keyword">case</span> MotionEvent.ACTION_MOVE: - <span class="keyword">return</span> handleActionMove(ev); - <span class="keyword">case</span> MotionEvent.ACTION_UP: - handleActionUp(ev); - <span class="keyword">break</span>; - } - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - } - - <span class="comment">/**</span> - <span class="comment"> * 按下事件处理</span> - <span class="comment"> * </span> - <span class="comment"> * @param ev</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> handleActionDown(MotionEvent ev) { - mDownX = ev.getX(); - mDownY = ev.getY(); - - mDownPosition = pointToPosition((<span class="keyword">int</span>) mDownX, (<span class="keyword">int</span>) mDownY); - - <span class="keyword">if</span> (mDownPosition == AdapterView.INVALID_POSITION) { - <span class="keyword">return</span>; - } - - mDownView = getChildAt(mDownPosition &#8211; getFirstVisiblePosition()); - - <span class="keyword">if</span> (mDownView != <span class="keyword">null</span>) { - mViewWidth = mDownView.getWidth(); - } - - <span class="comment">//加入速度检测</span> - mVelocityTracker = VelocityTracker.obtain(); - mVelocityTracker.addMovement(ev); - } - - - <span class="comment">/**</span> - <span class="comment"> * 处理手指滑动的方法</span> - <span class="comment"> * </span> - <span class="comment"> * @param ev</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> handleActionMove(MotionEvent ev) { - <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span> || mDownView == <span class="keyword">null</span>) { - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - } - - <span class="comment">// 获取X方向滑动的距离</span> - <span class="keyword">float</span> deltaX = ev.getX() &#8211; mDownX; - <span class="keyword">float</span> deltaY = ev.getY() &#8211; mDownY; - - <span class="comment">// X方向滑动的距离大于mSlop并且Y方向滑动的距离小于mSlop,表示可以滑动</span> - <span class="keyword">if</span> (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < mSlop) { - mSwiping = <span class="keyword">true</span>; - - <span class="comment">//当手指滑动item,取消item的点击事件,不然我们滑动Item也伴随着item点击事件的发生</span> - MotionEvent cancelEvent = MotionEvent.obtain(ev); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL | - (ev.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT)); - onTouchEvent(cancelEvent); - } - - <span class="keyword">if</span> (mSwiping) { - <span class="comment">// 跟谁手指移动item</span> - ViewHelper.setTranslationX(mDownView, deltaX); - <span class="comment">// 透明度渐变</span> - ViewHelper.setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f &#8211; 2f * Math.abs(deltaX)/ mViewWidth))); - - <span class="comment">// 手指滑动的时候,返回true,表示SwipeDismissListView自己处理onTouchEvent,其他的就交给父类来处理</span> - <span class="keyword">return</span> <span class="keyword">true</span>; - } - - <span class="keyword">return</span> <span class="keyword">super</span>.onTouchEvent(ev); - - } - - <span class="comment">/**</span> - <span class="comment"> * 手指抬起的事件处理</span> - <span class="comment"> * @param ev</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> handleActionUp(MotionEvent ev) { - <span class="keyword">if</span> (mVelocityTracker == <span class="keyword">null</span> || mDownView == <span class="keyword">null</span>|| !mSwiping) { - <span class="keyword">return</span>; - } - - <span class="keyword">float</span> deltaX = ev.getX() &#8211; mDownX; - - <span class="comment">//通过滑动的距离计算出X,Y方向的速度</span> - mVelocityTracker.computeCurrentVelocity(<span class="number">1000</span>); - <span class="keyword">float</span> velocityX = Math.abs(mVelocityTracker.getXVelocity()); - <span class="keyword">float</span> velocityY = Math.abs(mVelocityTracker.getYVelocity()); - - <span class="keyword">boolean</span> dismiss = <span class="keyword">false</span>; <span class="comment">//item是否要滑出屏幕</span> - <span class="keyword">boolean</span> dismissRight = <span class="keyword">false</span>;<span class="comment">//是否往右边删除</span> - - <span class="comment">//当拖动item的距离大于item的一半,item滑出屏幕</span> - <span class="keyword">if</span> (Math.abs(deltaX) > mViewWidth / <span class="number">2</span>) { - dismiss = <span class="keyword">true</span>; - dismissRight = deltaX > <span class="number"></span>; - - <span class="comment">//手指在屏幕滑动的速度在某个范围内,也使得item滑出屏幕</span> - } <span class="keyword">else</span> <span class="keyword">if</span> (mMinFlingVelocity <= velocityX - && velocityX <= mMaxFlingVelocity && velocityY < velocityX) { - dismiss = <span class="keyword">true</span>; - dismissRight = mVelocityTracker.getXVelocity() > <span class="number"></span>; - } - - <span class="keyword">if</span> (dismiss) { - ViewPropertyAnimator.animate(mDownView) - .translationX(dismissRight ? mViewWidth : -mViewWidth)<span class="comment">//X轴方向的移动距离</span> - .alpha(<span class="number"></span>) - .setDuration(mAnimationTime) - .setListener(<span class="keyword">new</span> AnimatorListenerAdapter() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationEnd(Animator animation) { - <span class="comment">//Item滑出界面之后执行删除</span> - performDismiss(mDownView, mDownPosition); - } - }); - } <span class="keyword">else</span> { - <span class="comment">//将item滑动至开始位置</span> - ViewPropertyAnimator.animate(mDownView) - .translationX(<span class="number"></span>) - .alpha(<span class="number">1</span>) - .setDuration(mAnimationTime).setListener(<span class="keyword">null</span>); - } - - <span class="comment">//移除速度检测</span> - <span class="keyword">if</span>(mVelocityTracker != <span class="keyword">null</span>){ - mVelocityTracker.recycle(); - mVelocityTracker = <span class="keyword">null</span>; - } - - mSwiping = <span class="keyword">false</span>; - } - - - - <span class="comment">/**</span> - <span class="comment"> * 在此方法中执行item删除之后,其他的item向上或者向下滚动的动画,并且将position回调到方法onDismiss()中</span> - <span class="comment"> * @param dismissView</span> - <span class="comment"> * @param dismissPosition</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> performDismiss(<span class="keyword">final</span> View dismissView, <span class="keyword">final</span> <span class="keyword">int</span> dismissPosition) { - <span class="keyword">final</span> ViewGroup.LayoutParams lp = dismissView.getLayoutParams();<span class="comment">//获取item的布局参数</span> - <span class="keyword">final</span> <span class="keyword">int</span> originalHeight = dismissView.getHeight();<span class="comment">//item的高度</span> - - ValueAnimator animator = ValueAnimator.ofInt(originalHeight, <span class="number"></span>).setDuration(mAnimationTime); - animator.start(); - - animator.addListener(<span class="keyword">new</span> AnimatorListenerAdapter() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationEnd(Animator animation) { - <span class="keyword">if</span> (onDismissCallback != <span class="keyword">null</span>) { - onDismissCallback.onDismiss(dismissPosition); - } - - <span class="comment">//这段代码很重要,因为我们并没有将item从ListView中移除,而是将item的高度设置为0</span> - <span class="comment">//所以我们在动画执行完毕之后将item设置回来</span> - ViewHelper.setAlpha(dismissView, 1f); - ViewHelper.setTranslationX(dismissView, <span class="number"></span>); - ViewGroup.LayoutParams lp = dismissView.getLayoutParams(); - lp.height = originalHeight; - dismissView.setLayoutParams(lp); - - } - }); - - animator.addUpdateListener(<span class="keyword">new</span> ValueAnimator.AnimatorUpdateListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onAnimationUpdate(ValueAnimator valueAnimator) { - <span class="comment">//这段代码的效果是ListView删除某item之后,其他的item向上滑动的效果</span> - lp.height = (Integer) valueAnimator.getAnimatedValue(); - dismissView.setLayoutParams(lp); - } - }); - - } - - <span class="comment">/**</span> - <span class="comment"> * 删除的回调接口</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">interface</span> OnDismissCallback { - <span class="keyword">public</span> <span class="keyword">void</span> onDismiss(<span class="keyword">int</span> dismissPosition); - } - - } 看过Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果你会发现,这个自定义的SwipeDismissListView只重写了onTouchEvent()方法,其实我们重写这一个方法就能实现我们需要的效果 ...

2015年3月7日 · 9 分钟 · 天边的星星

android ViewPage动画实现

实现思路 1.使用http://nineoldandroids.com/动画库 https://github.com/JakeWharton/NineOldAndroids https://github.com/jfeinstein10/JazzyViewPager 2.使用3.0以上直接使用 3.自定义Viewpage

2015年3月7日 · 1 分钟 · 天边的星星

直接拿来用!最火的Android开源项目

 **21. [drag-sort-listview](https://github.com/bauerca/drag-sort-listview)** DragSortListView(DSLV)是Android ListView的一个扩展,支持拖拽排序和左右滑动删除功能。重写了TouchInterceptor(TI)类来提供更加优美的拖拽动画效果。 [![](http://cms.csdnimg.cn/article/201305/06/5187781b64cbe_middle.jpg)](http://cms.csdnimg.cn/article/201305/06/5187781b64cbe.jpg) [![](http://cms.csdnimg.cn/article/201305/06/5187782519829_middle.jpg)](http://cms.csdnimg.cn/article/201305/06/5187782519829.jpg) DSLV主要特性: - 完美的拖拽支持; - 在拖动时提供更平滑的滚动列表滚动; - 支持每个ListItem高度的多样性 - 公开startDrag()和stopDrag()方法; - 有公开的接口可以自定义拖动的View。 DragSortListView适用于带有任何优先级的列表:收藏夹、播放列表及清单等,算得上是目前Android开源实现拖动排序操作最完美的方案。 **22. [c-geo-opensource](https://github.com/cgeo/c-geo-opensource)** c:geo是Android设备上一个简单而又强大的非官方地理寻宝客户端。与其他类似应用不同的是,c:geo不需要Web浏览器,也不需要文件输出。你可以在毫无准备的情况下,毫无后顾之忧地带上你的智能手机去进行地理寻宝。当然,你也不需要付钱,因为它是免费的。 [![](http://cms.csdnimg.cn/article/201305/07/518894ed23ed2_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/518894ed23ed2.jpg) c-geo-opensource包含了c:geo所有开源代码。 详情请参考:[**c:geo**](http://www.cgeo.org/) **23. [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids)** 自Android 3.0以上的版本,SDK新增了一个android.animation包,里面的类都是跟动画效果实现相关的,通过Honeycomb API,能够实现非常复杂的动画效果。但如果开发者想在3.0以下的版本中也能使用到这套API,那么Nine Old Androids就会是你最好的选择,该API和Honeycomb API完全一样,只是改变了你使用com.nineoldandroids.XXX的入口。 [![](http://cms.csdnimg.cn/article/201305/07/51889435c4f33_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/51889435c4f33.jpg) 该项目包含两个工程,一个是Library,即为动画效果的实现库,另一个则是Sample,是对如何使用该API的演示。开发者可以直接登陆Google Play下载安装[**Nine Old Androids Sample**](https://play.google.com/store/apps/details?id=com.jakewharton.nineoldandroids.sample),查看演示。 详情请参考:[**Nine Old Androids**](http://nineoldandroids.com/) **24. [ppsspp](https://github.com/hrydgard/ppsspp)** PPSSPP是由GC/Wii模拟器[**Dolphin**](http://dolphin-emu.org/)联合创始人之一Henrik Rydgård开发的一款免费的跨平台开源模拟器,支持Windows、Linux、Mac、Android、iOS、BlackBerry 10等主流计算机与移动操作系统,可直接工作在x86、x64、ARM等CPU平台上,以GNU GPLv2许可协议发布,主要使用C++编写以提高效率和可移植性。 [![](http://cms.csdnimg.cn/article/201305/06/518779953e825_middle.jpg)](http://cms.csdnimg.cn/article/201305/06/518779953e825.jpg) 只要支持OpenGL ES 2.0,PPSSPP就可以在相当低规格的硬件设备上运行,包括基于ARM的手机及平板电脑。 详情请参考:[**PPSSPP**](http://www.ppsspp.org/) **25. [androidquery](https://github.com/androidquery/androidquery)** Android-Query(AQuery)是一个轻量级的开发包,用于实现Android上的异步任务和操作UI元素,可让Android应用开发更简单、更容易,也更有趣。 **26. [droid-fu](https://github.com/mttkay/droid-fu)** Droid-Fu是一个开源的通用Android应用库,其主要目的是为了让Android开发更容易,包含有许多工具类,还有非常易用的Android组件。 Droid-Fu提供支持的领域包括: - Android应用的生命周期帮助 - 支持处理Intents和diagnostics类 - 后台任务支持 - HTTP消息处理 - 对象、HTTP响应及远程图像高速缓存 - 定制各种Adapter及View [![](http://cms.csdnimg.cn/article/201305/07/518897f7199f4_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/518897f7199f4.jpg) Droid-Fu最大的优势在于它的应用生命周期帮助类,如果你正在开发一款Android应用,而它的主要任务是运行后台任务,比如从Web上抓取数据,那么,你一定会使用到Droid-Fu,不过,目前该项目在GitHub上已经停止更新维护。 详情请参考:[**droid-fu**](https://github.com/mttkay/droid-fu/wiki) **27. [TextSecure](https://github.com/WhisperSystems/TextSecure)** TextSecure是Whisper Systems团队开发的一个Android上的加密信息客户端,旨在增强用户和企业通信的安全性,其源代码于2011年被Twitter发布在GitHub开源数据库中。 [![](http://cms.csdnimg.cn/article/201305/07/51889740c3bd3_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/51889740c3bd3.jpg) 该软件允许用户将在Android设备上所有发送和接收的短信内容进行加密,还可以将加密信息发送给另一个TextSecure用户。 **28. [XobotOS](https://github.com/xamarin/XobotOS)** XobotOS是Xamarin的一个研究项目,用于将Android 4.0从Java/Dalvik移植到C#,并对移植后的性能及内存占用情况进行检测。 [![](http://cms.csdnimg.cn/article/201305/06/518779fcb89b9_middle.jpg)](http://cms.csdnimg.cn/article/201305/06/518779fcb89b9.jpg) **29. [ignition](https://github.com/mttkay/ignition)** 在编写Android应用时,通过提供即用组件和包含许多样板文件的实用类,ignition可以让你的Android应用快速起步。ignition涵盖的区域包括: - Widget、Adapter、Dialog等UI组件; - 允许编写简单却强大的网络代码的HTTP Wrapper库; - 加载远程Web图像并进行缓存的类; - 简单但有效的缓存框架(将对所有对象树做出响应的HTTP缓存到内存或硬盘中); - Intents、diagnostics等几个能让API级别更容易向后兼容的帮助类; - 更友好、更强大的AsyncTask实现。 [![](http://cms.csdnimg.cn/article/201305/07/51889448dd732_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/51889448dd732.jpg) ignition包括三个子项目: - ignition-core——是一个可以直接编译到App中的Android库项目。 - ignition-support——一个标准的Java库项目,被部署为一个普通的JAR,包含了大部分实用工具类。开发者可以独立使用该工程的核心模块。 - ignition-location——一个可以直接编译到应用程序中的Android AspectJ库项目。能够让定位应用在不需要Activity位置更新处理的情况下获取到最新的位置信息。 详情请参考:[**ignition Sample applications**](https://github.com/mttkay/ignition/wiki/Sample-applications) **30. [android_page_curl](https://github.com/harism/android_page_curl)** android_page_curl是一个在Android上使用OpenGL ES实现类似书本翻页效果的示例程序。(点击链接查看[**视频演示**](http://www.youtube.com/watch?v=iwu7P5PCpsw)) [![](http://cms.csdnimg.cn/article/201305/07/51889b43ec9e9_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/51889b43ec9e9.jpg) **31. [asmack](https://github.com/Flowdalic/asmack)** 说到aSmack,自然要先提提Smack。Smack API是一个完整的实现了XMPP协议的开源API库,而aSmack则是Smack在Android上的构建版本,于2013年2月初迁移到GitHub上,该资源库并不包含太多的代码,只是一个构建环境。开发者可以利用该API进行基于XMPP协议的即时消息应用程序开发。 详情请参考:[**asmack**](https://code.google.com/p/asmack/) **32. [AndroidBillingLibrary](https://github.com/robotmedia/AndroidBillingLibrary)** In-app Billing是一项Google Play服务,能够让你在应用内进行数字内容销售,可销售的数字内容范围非常广,包括媒体文件、照片等下载内容,还包括游戏级别、药剂、增值服务和功能等虚拟内容。Android Billing Library可以实现In-app Billing的所有规范,并提供更高级的类来进行使用。 [![](http://cms.csdnimg.cn/article/201305/07/5188ae278fb5a_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5188ae278fb5a.jpg) Google于2012年底正式发布了v3版Android In-app Billing,但截至目前,GitHub上的Android Billing Library还只能支持到v2版,据悉Google将于2013年初对它进行更新。 详情请参考:[**Google Play In-app Billing**](http://developer.android.com/google/play/billing/index.html) **33. [Crouton](https://github.com/keyboardsurfer/Crouton)** Crouton是Android上的一个可以让开发者对环境中的Toast进行替换的类,以一个应用程序窗口的方式显示,而其显示位置则由开发者自己决定。 [![](http://cms.csdnimg.cn/article/201305/07/5188b6491fd81_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5188b6491fd81.jpg) 开发者可以直接登陆Google Play下载安装[**Crouton Demo**](https://play.google.com/store/apps/details?id=de.keyboardsurfer.app.demo.crouton),查看应用演示。 **34. [cwac-endless](https://github.com/commonsguy/cwac-endless)** CommonsWare Android Components(CWAC)是一个开源的Android组件库,用来解决Android开发中各个方面的常见问题,每个 CWAC组件打包成一个独立的jar文件,其中就包含cwac-endless。 [![](http://cms.csdnimg.cn/article/201305/07/5188ca3020955_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5188ca3020955.jpg) cwac-endless提供一个EndlessAdapter,这是一个自动分页的List,当用户浏览到List最后一行时自动请求新的数据。 详情请参考:[**Commons Ware**](http://commonsware.com/cwac) **35. [DiskLruCache](https://github.com/JakeWharton/DiskLruCache)** 在Android应用开发中,为了提高UI的流畅性、响应速度,提供更高的用户体验,开发者常常会绞尽脑汁地思考如何实现高效加载图片,而DiskLruCache实现正是开发者常用的图片缓存技术之一。Disk LRU Cache,顾名思义,硬件缓存,就是一个在文件系统中使用有限空间进行高速缓存。每个缓存项都有一个字符串键和一个固定大小的值。 [![](http://cms.csdnimg.cn/article/201305/07/5188fc60a7729_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5188fc60a7729.jpg) 点击链接[**下载**](http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.jakewharton&a=disklrucache&v=LATEST)该库项目。 **36. [Android-SlideExpandableListView](https://github.com/tjerkw/Android-SlideExpandableListView)** 如果你对Android提供的Android ExpandableListView并不满意,一心想要实现诸如Spotify应用那般的效果,那么SlideExpandableListView绝对是你最好的选择。该库允许你自定义每个列表项目中的ListView,一旦用户点击某个按钮,即可实现该列表项目区域滑动。 [![](http://cms.csdnimg.cn/article/201305/07/5188ff9b1a21b_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5188ff9b1a21b.jpg) **37. [gauges-android](https://github.com/github/gauges-android)** Gaug.es for Android是由[**gaug.es**](http://get.gaug.es/)推出的一款在Android设备上对网站流量数据进行实时统计的应用。gauges-android包含了该应用的源代码,开发者可以直接登陆[**Google Play**](https://play.google.com/store/apps/details?id=com.github.mobile.gauges)下载安装该应用。 [![](http://cms.csdnimg.cn/article/201305/07/5189035ebf373_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5189035ebf373.jpg) **38. [acra](https://github.com/ACRA/acra)** ACRA是一个能够让Android应用自动将崩溃报告以谷歌文档电子表的形式进行发送的库,旨在当应用发生崩溃或出现错误行为时,开发者可以获取到相关数据。 [![](http://cms.csdnimg.cn/article/201305/07/5189057f9195e_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/5189057f9195e.jpg) **39. [roboguice](https://github.com/roboguice/roboguice)** RoboGuice是Android平台上基于Google Guice开发的一个库,可以大大简化Android应用开发的代码及一些繁琐重复的代码。给Android带来了简单、易用的依赖注入,如果你使用过Spring或Guice的话,你就会知道这种编程方式是多么的便捷。 [![](http://cms.csdnimg.cn/article/201305/07/518906ff6405e_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/518906ff6405e.jpg) **40. [otto](https://github.com/square/otto)** Otto是由Square发布的一个着重于Android支持的基于Guava的强大的事件总线,在对应用程序不同部分进行解耦之后,仍然允许它们进行有效的沟通。 [![](http://cms.csdnimg.cn/article/201305/07/51890a97dcfc6_middle.jpg)](http://cms.csdnimg.cn/article/201305/07/51890a97dcfc6.jpg) 详情请参考:**[Otto](http://square.github.io/otto/)** - [直接拿来用!最火的Android开源项目(完结篇)](http://www.csdn.net/article/1970-01-01/2815370) - [直接拿来用!最火的iOS开源项目(二)](http://www.csdn.net/article/1970-01-01/2815806) - [直接拿来用!最火的iOS开源项目(三)](http://www.csdn.net/article/1970-01-01/2816230) - [直接拿来用!最火的iOS开源项目(一)](http://www.csdn.net/article/1970-01-01/2815530) - [直接拿来用!Facebook移动开源项目大合集](http://www.csdn.net/article/1970-01-01/2819435) </div>

2015年3月7日 · 1 分钟 · 天边的星星