Android资源推荐

AndroidDevTools Google Android官方教程 Android Training Course in Chinese Android基础 上面可能是一个比较全面系统的培训教程,对于新手们可能对某些需要着重掌握的东西比较迷茫,于是整理下个人认为新手们必须要掌握的知识点,顺便也会附带相应觉得不错的讲解博客地址。 两分钟彻底让你明白Android Activity生命周期(图文)! Activity实际开发中使用频率最高,这个必须要理解 Android四大基本组件介绍与生命周期 Android中的四大组件必须得知道,也是面试常问到的 ListView的基本使用与优化 ListView是所有控件中最常使用且对新手来说比较复杂的用法,各种Adapter的使用以及ListView的优化都是必须掌握的 Android系统用于Activity的标准Intent Intent解决了Android中四大组件的通讯,非常有用,这篇博客收集整理了系统的标准Intent Android 屏幕适配 介绍一些Android屏幕适配的基础 Android中SQLite应用详解 Android中的SQLite需要掌握,这篇博客很适合新手 Android Fragment完全解析 3.0之后新加的Fragment,必须要掌握,目前使用的场景也是越来越普遍了 Android中级 Android应用程序的生命周期 Android的应用程序的生命周期需要理解,面试也是经常会被问的 带你一步步深入了解View View做为UI开发中最常用到的,必须要深入理解 Android Service完全解析 Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色 Android Gson 目前比较常用比较流行的数据格式就是json了,这篇博客教你如何使用Google Gson库来进行json解析 Android 布局优化 Android开发中经常会用到xml布局,那么布局优化方面的知识更是需要掌握的了 Android中Intent传递对象的两种方法(Serializable,Parcelable) 详细讲解了Android中Intent中如何传递对象 Android异步消息处理机制完全解析 Android开发中异步操作是经常使用的,必须理解掌握 Android AsyncTask完全解析 Android异步操作的另一种方法 Android Custom Loading 很早的一个小demo,教你如何做一个App的Loading动画 Android进阶 Android Gradle Google官方Android新的构建系统,可以很方便的管理依赖、编译打包等 Android 性能优化 一系列的性能调优教程,让你的代码以及App更畅通! 一个完整的开源项目–9GAG 一个开源客户端,教你使用Studio、Gradle以及一些流行的开源库快速开发一个不错的Android客户端 整理的Android开发资源 自己整理的一些Android开发资源,包括开发、工具、设计等,相信会对你有用的 Android设计 在开发一款Android App之前,你需要了解下Android平台的设计规范,这里有一系列关于Android Design的讲解以及Google最新推出的Material Design中文翻译版 Android Design Material Design Android兼容库 在了解了设计规范准备着手开发你的App时,你还需要考虑你的App支持的版本,如果是全新的App,从目前的市场份额来看,建议直接支持4.0+,虽然2.3的份额仍然有一部分,但是这部分真正用来使用App的人又能有多少呢。当然如果你的公司必须要求支持2.x的版本,那么也不用担心,下面整理了几个满足你适配的一些兼容库: ...

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

Android常用方法收集

/** 获取当前应用程序的版本号 */ private String getVersion() { String st = getResources().getString(R.string.Version_number_is_wrong); PackageManager pm = getPackageManager(); try { PackageInfo packinfo = pm.getPackageInfo(getPackageName(), 0); String version = packinfo.versionName; return version; } catch (NameNotFoundException e) { e.printStackTrace(); return st; } } 设置字符串点击启动指定Activity,部分字体高亮显示 // 创建一个 SpannableString对象 SpannableString sp = <span class="s1">new</span> SpannableString( <span class="s2"> getString(R.string.</span>activity_frogetpwd_newuserreader_str<span class="s2">));</span> // 设置超链接 <span class="s2"> Spanned.</span>SPAN_EXCLUSIVE_EXCLUSIVE<span class="s2">);</span> // 设置背景高亮样式一 // sp.setSpan(new BackgroundColorSpan(Color.RED), 17, 19, // Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 设置高亮样式二 <span class="s2"> Spannable.</span>SPAN_EXCLUSIVE_EXCLUSIVE<span class="s2">);</span> // // 设置斜体 // sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 27, // 29, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); myTextView.setText(sp); // 设置TextView可点击 myTextView.setMovementMethod(LinkMovementMethod.getInstance()); /** * 自定义URLSpan的点击事件 * * <span class="s1">@author</span> <span class="s2">jason</span> * */ <span class="s3">private</span> <span class="s3">class</span> MyURLSpan <span class="s3">extends</span> ClickableSpan { <span class="s3">private</span> String <span class="s4">mUrl</span>; MyURLSpan(String url) { <span class="s4">mUrl</span> = url; } @Override <span class="s3">public</span> <span class="s3">void</span> onClick(View widget) { Toast.makeText(RegisterActivity.<span class="s3">this</span>, <span class="s4">mUrl</span>, Toast.<span class="s4">LENGTH_LONG</span>) .show(); widget.setBackgroundColor(Color.parseColor(<span class="s6">&#8220;#00000000&#8221;</span>)); } }

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

Android自定义控件系列之应用篇——圆形进度条

**一、概述** 在上一篇博文中,我们给大家介绍了Android自定义控件系列的基础篇。链接: http://www.cnblogs.com/jerehedu/p/4360066.html 这一篇博文中,我们将在基础篇的基础上,再通过重写ondraw()方法和自定义属性实现圆形进度条,效果如图所示: **二、实现步骤** 1、 编写自定义组件MyCircleProgress扩展View <span class="keyword">public</span> <span class="class"><span class="keyword">class</span></span><span class="class"> <span class="title">MyCircleProgress</span> <span class="keyword">extends</span> <span class="title">View</span> {</span> … } 2、 在MyCircleProgress类中,定制属性 <span class="keyword">public</span> <span class="keyword">int</span> progress = <span class="number"></span>;<span class="comment">//</span><span class="comment">进度实际值,当前进度</span> <span class="javadoc">/**</span><span class="javadoc"> * 自定义控件属性,可灵活的设置圆形进度条的大小、颜色、类型等 */</span> <span class="keyword">private</span> <span class="keyword">int</span> mR;<span class="comment">//</span><span class="comment">圆半径,决定圆大小</span> <span class="keyword">private</span> <span class="keyword">int</span> bgColor;<span class="comment">//</span><span class="comment">圆或弧的背景颜色</span> <span class="keyword">private</span> <span class="keyword">int</span> fgColor;<span class="comment">//</span><span class="comment">圆或弧的前景颜色,即绘制时的颜色</span> <span class="keyword">private</span> <span class="keyword">int</span> drawStyle; <span class="comment">//</span><span class="comment">绘制类型 FILL画圆形进度条,STROKE绘制弧形进度条</span> <span class="keyword">private</span> <span class="keyword">int</span> strokeWidth;<span class="comment">//</span><span class="comment">STROKE绘制弧形的弧线的宽度</span> <span class="keyword">private</span> <span class="keyword">int</span> max;<span class="comment">//</span><span class="comment">最大值,设置进度的最大值</span> <span class="javadoc">/**</span><span class="javadoc"> * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 */</span> <span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> setProgress(<span class="keyword">int</span> progress) { <span class="keyword">if</span>(progress&lt;<span class="number"></span>){ progress=<span class="number"></span>; }<span class="keyword">else</span> <span class="keyword">if</span>(progress&gt;max){ progress=max; }<span class="keyword">else</span>{ <span class="keyword">this</span>.progress = progress; } } <span class="keyword">public</span> <span class="keyword">int</span> getMax() { <span class="keyword">return</span> max; } 3、 为定制的属性编写attrs.xml资源,该资源文件放在res/values目录下,内容如下: ...

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

java中byte与 int、short、char、float、double之间的转换

由于java的字节序和网络字节序一致(高位在前),给出换算方法,亲测OK public static void main(String[] args) { byte[] bs=new byte[2]; short dvalue=1; Utils.putShort(bs, dvalue, 0); for (int i = 0; i < bs.length; i++) { System.out.println(bs[i]); } } /** 将32位的int值放到4字节的里 @param num @return */ public static byte[] int2byteArray(int num) { byte[] result = new byte[4]; result[0] = (byte) (num »> 24);// 取最高8位放到0下标 result[1] = (byte) (num »> 16);// 取次高8为放到1下标 result[2] = (byte) (num »> 8); // 取次低8位放到2下标 result[3] = (byte) (num); // 取最低8位放到3下标 return result; } /** ...

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

android多分辨率多屏幕密度下UI适配方案

相关概念 **分辨率:**整个屏幕的像素数目,为了表示方便一般用屏幕的像素宽度(水平像素数目)乘以像素高度表示,形如1280×720,反之分辨率为1280×720的屏幕,像素宽度不一定为1280 **屏幕密度:**表示单位面积内的像素个数,通常用dpi为单位,即每英寸多少个像素点 px**:**长度单位,以具体像素为单位 dp**:**长度单位,与具体屏幕密度无关,显示的时候根据具体平台屏幕密度的不同最终转换为相应的像素长度,具体转换规则是: 1dp =(目标屏幕密度/标准密度)*px,标准密度为160dpi,例如,1dp长度在密度为160dpi的平台表示一个像素的长度,而在240dpi的平台则表示1.5个像素的长度 **屏幕尺寸:**屏幕的大小,通常用屏幕对角线的长度表示 Android界面适配机制 UI界面在不同平台的适配受屏幕尺寸和屏幕密度影响,Android适配机制就是在资源后面添加对这两种因素的限定,通过不同的限定区分不同的平台资源,Android在使用资源的时候会优先选择满足本平台限定的资源,再找最接近条件的,再找默认(即不加限定),通过选择适合当前平台的资源来完成不同平台的适配。 屏幕尺寸分为:small,normal,large,xlarge分别表示小,中,大,超大屏 屏幕密度分为:ldpi,mdpi,hdpi,xhdpi,它们的标准值分别是:120dpi,160dpi,240dpi,320dpi 以上划分均表示的是一个范围: 在资源目录后面加上上面的限定就能为资源指定特定的适用平台,如下所示 表示大屏,中密度布局会选择上面那个main.xml,超大屏,中密度会选择下面那个main.xml 在实际开发过程中屏幕尺寸不够直观,android将其转换为分辨率表示,根据屏幕具体分辨率可选择相应的限定符 小结:通过加上上述限定可以实现一个apk适配几种主流的屏幕尺寸和屏幕密度,这种限定方式比较适用于对外发布应用,不知道终端具体参数的情况,但是不能做到精确适配,对于屏幕尺寸和密度相差不大的两种平台不能很好的区分。 为了解决上述问题,自Android3.2开始,引入了精确适配,理论上可以适配任意像素宽度,高度,屏幕密度的平台,需用以下方式添加限定符 其中w1280dp表示屏幕宽度为1280dp,h752dp表示屏幕高度为752dp,160dpi表示屏幕密度,其中屏幕宽,高必须以dp为单位,在知道屏幕像素宽高度的情况下可以通过公式:1dp = (目标屏幕密度/标准密度)*px 转换成dp单位。 例如:某平台屏幕宽,高分别为1920px,720px,屏幕密度为240dpi 适配该平台的限定为: 或者 根据公式1dp=(240/160)px=1.5px,宽度,高度转为dp单位分别是1280dp和480dp. Android自适应不同分辨率或不同屏幕大小的layout布局(横屏|竖屏) 一:不同的layout Android手机屏幕大小不一,有480×320, 640×360, 800×480.怎样才能让App自动适应不同的屏幕呢? 其实很简单,只需要在res目录下创建不同的layout文件夹,比如layout-640×360,layout-800×480,所有的layout文件在编译之后都会写入R.java里,而系统会根据屏幕的大小自己选择合适的layout进行使用。 二:hdpi、mdpi、ldpi 在之前的版本中,只有一个drawable,而2.1版本中有drawable-mdpi、drawable-ldpi、drawable-hdpi三个,这三个主要是为了支持多分辨率。 drawable- hdpi、drawable- mdpi、drawable-ldpi的区别: (1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480×800),FWVGA (480×854) (2)drawable-mdpi里面存放中等分辨率的图片,如HVGA (320×480) (3)drawable-ldpi里面存放低分辨率的图片,如QVGA (240×320) 系统会根据机器的分辨率来分别到这几个文件夹里面去找对应的图片。 更正:应该是对应不同density 的图片 在开发程序时为了兼容不同平台不同屏幕,建议各自文件夹根据需求均存放不同版本图片。 [i]备注:三者的解析度不一样,就像你把电脑的分辨率调低,图片会变大一样,反之分辨率高,图片缩小。 [/i] 屏幕方向: 横屏竖屏自动切换: 可以在res目录下建立layout-port-800×600和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件,这样在手机屏幕方向变化的时候系统会自动调用相应的布局文件,避免一种布局文件无法满足两种屏幕显示的问题。 不同分辨率横屏竖屏自动切换: 以800×600为例 可以在res目录下建立layout-port-800×600和layout-land-800×600两个目录 不切换: 以下步骤是网上流传的,不过我自己之前是通过图形化界面实现这个配置,算是殊途同归,有空我会把图片贴上来。 还要说明一点:每个activity都有这个属性screenOrientation,每个activity都需要设置,可以设置为竖屏(portrait),也可以设置为无重力感应(nosensor)。 要让程序界面保持一个方向,不随手机方向转动而变化的处理办法: 在AndroidManifest.xml里面配置一下就可以了。加入这一行android:screenOrientation=”landscape”。 例如(landscape是横向,portrait是纵向): Java代码: <?xml version=”1.0″ encoding=”utf-8″?> <manifestxmlns:android=”http://schemas.android.com/apk/res/android” package=”com.ray.linkit” android:versionCode=”1″ android:versionName=”1.0″> <application android:icon=”@drawable/icon”android:label=”@string/app_name”> 另外,android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置,那样,进行中的游戏就不会自动重启了! 有的程序适合从竖屏切换到横屏,或者反过来,这个时候怎么办呢?可以在配置Activity的地方进行如下的配置android:screenOrientation=”portrait”。这样就可以保证是竖屏总是竖屏了,或者landscape横向。 而 有的程序是适合横竖屏切换的。如何处理呢?首先要在配置Activity的时候进行如下的配 置:android:configChanges=”keyboardHidden|orientation”,另外需要重写Activity的 onConfigurationChanged方法。实现方式如下,不需要做太多的内容: ...

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

oschina-app源码分析-提醒标签BadgeView使用方法https://github.com/chenupt/BezierDemo

看过oschina-app的数字提醒标签BadgeView的使用过程,才发现以前项目中的实现逻辑有问题。以前待的项目组没个牛人,从我干第一个项目就我负责开发设计和管理,可想而知,顶多也就实现功能交工。说到底就是经验不足,所以有时间还是多看看别人的代码。本来是想主要讲oschina-app里面提醒标签的实现逻辑,但我觉得标签控件BadgeView有必要说下。 BadgeView是一个开源的ui项目,其实就一个ui工具类,BadgeView是对TextView的重写,他的代码就不贴了,可以到git上下最新的吧:https://github.com/jgilfelt/android-viewbadger 在这里主要说下他的用法,它可以设置标签的背景、颜色、位置、动画、文字等,对一般的需求足以满足了,先看下git上demo的效果: 默认属性标签代码: **[java]** [view plain](http://blog.csdn.net/xiangxue336/article/details/21073571#)[copy](http://blog.csdn.net/xiangxue336/article/details/21073571#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/230977)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/230977/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="comment">// *** default badge ***</span> - - View target = findViewById(R.id.default_target); - BadgeView badge = <span class="keyword">new</span> BadgeView(<span class="keyword">this</span>, target); - badge.setText(<span class="string">&#8220;1&#8221;</span>); - badge.show(); 默认是显示在右上角,红色的背景白色字体,这些个默认属性是可以在BadgeView里面设置的。 设置position代码: **[java]** [view plain](http://blog.csdn.net/xiangxue336/article/details/21073571#)[copy](http://blog.csdn.net/xiangxue336/article/details/21073571#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/230977)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/230977/fork) <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> </div> - <span class="comment">// *** set position ***</span> - - btnPosition = (Button) findViewById(R.id.position_target); - badge1 = <span class="keyword">new</span> BadgeView(<span class="keyword">this</span>, btnPosition); - badge1.setText(<span class="string">&#8220;12&#8221;</span>); - badge1.setBadgePosition(BadgeView.POSITION_CENTER); - btnPosition.setOnClickListener(<span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) { - badge1.toggle(); - } - }); toggle方法是控制标签的现实和隐藏的。 ...

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

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 分钟 · 天边的星星