GitHub 上排名前 100 的 Android 开源库简介

本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择 (Best Match) 得到的结果, 然后过滤了跟Android不相关的项目, 所以排名并不具备任何官方效力, 仅供参考学习, 方便初学者快速了解当前一些流行的Android开源库. iOS 版本的在此: https://github.com/Aufree/trip-to-iOS/blob/master/Top-100.md 感谢 @GitHubDaily 的大力支持, 以及 @stormzhang 的指点 若有任何疑问可通过邮件或微博联系我 项目名称 <th> 项目简介 </th> 1. [react-native](https://github.com/facebook/react-native) <td width="275"> 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native, 该框架结合了 Web 应用和 Native 应用的优势, 可以使用 JavaScript 来开发 iOS 和 Android 原生应用 </td> 2.[Android-Universal-Image-Loader](https://github.com/nostra13/Android-Universal-Image-Loader) <td width="275"> ImageLoader 是最早开源的 Android 图片缓存库, 强大的缓存机制, 早期被广泛 Android 应用使用, 至今仍然有很多 Android 开发者在使用 </td> 3. [RxJava](https://github.com/ReactiveX/RxJava) <td width="275"> RxJava 是一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库, 简单来说它就是一个实现异步操作的库, RxJava 的优点在于一个词 &#8220;简洁&#8221;, 使用它就算你程序逻辑有多么复杂, 它依然能够保持简洁易懂 </td> 4. [retrofit](https://github.com/square/retrofit) <td width="275"> Retrofit 是 Square 公司出品的 HTTP 请求库, 同时是 Square 是最早开源项目之一, Retrofit 是目前 Android 最流行的 Http Client 库之一, 目前版本是 Retrofit2.0 Beta4, 越来越多 Android 开发者开始使用这个请求库了 </td> 5. [okhttp](https://github.com/square/okhttp) <td width="275"> OkHttp 是 Square 公司出品的 HTTP 另一个请求库, Google 不推荐人们使用 HttpClient, 可是 HttpURLConnection 实在是太难用了, 因此很多人使用了 OkHttp 来解决这问题, 据说 Android4.4 的源码中可以看到 HttpURLConnection 已经替换成 OkHttp 实现呢 </td> 6. [SlidingMenu(不建议使用)](https://github.com/jfeinstein10/SlidingMenu) <td width="275"> 一个侧滑菜单开源库, 在 Google 自己原生态的侧滑菜单 NavigationDrawer 没有出现之前, 这个库就已经被广泛使用, 可是到现在这个库已经被放弃了 </td> 7. [picasso](https://github.com/square/picasso) <td width="275"> Picasso 是 Square 公司出品的一款图片缓存库, 主导者是 JakeWharton 大神 </td> 8. [android-best-practices](https://github.com/futurice/android-best-practices) <td width="275"> Android 开发最佳实践, 里面所介绍的经验都是来自于 Futurice 公司 Android 开发者, 介绍内容有 Android 开发规范、架构、布局技巧, 以及使用一些有助于快速开发相关工具等等, 非常适合新手去学习 </td> 9. [EventBus](https://github.com/greenrobot/EventBus) <td width="275"> EventBus 是 Android 事件管理总线, 使用它可以替带 Android BroadCast, BroadCastReceiver, Handler 在 Activity, Fragment, Service, 线程之间传递消息, 大大简化了事件传递逻辑 </td> 10. [android-async-http](https://github.com/loopj/android-async-http) <td width="275"> Android-Async-Http 是 Android 一款老牌异步请求库, 专门对 Android 在 Apache 的 HttpClient 基础上构建的异步 http 连接, 该库有很多特征, 例如: 库的 size 小, 支持文件上传不需使用第三方库支持, 内部使用线程池来处理并发, 等等 </td> 11. [fresco](https://github.com/facebook/fresco) <td width="275"> Fresco 是 FaceBook 公司出品的一款图片缓存库, Fresco 是一个强大的图片加载组件, 支持加载 Gif 图和 WebP 格式, 支持 Android2.3(API level 9) 及其以上系统, Fresco 中设计了 Image pipeline 和 Drawees 两个模块各施其职, 使得图片完美加载出来, 想知道更多 image pipeline 和 Drawees 有关于它的特性, 可以到它[官方平台](http://fresco-cn.org/)看介绍 </td> 12. [zxing](https://github.com/zxing/zxing) <td width="275"> ZXing 是二维码领域中名气最大的开源项目, 它提供了多个平台的二维码/条形码扫描解决方案, 拥有扫描快, 识别率高, 使用简单等特点 </td> 13. [leakcanary](https://github.com/square/leakcanary) <td width="275"> LeakCanary 是 Square 公司出的一款检测内存泄露工具, 该工具能帮助你在开发阶段方便的检测出内存泄露的问题, 使用起来非常简单方便 </td> 14. [butterknife](https://github.com/JakeWharton/butterknife) <td width="275"> 由 JakeWharton 大神开发出来的, ButterKnife 是 View 注入框架, 使用它为了简写很多 findViewById 代码, 同时还支持 View 的一些事件处理函数 </td> 15. [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) <td width="275"> MPAndroidChart 是一款强大的 Android 图表库, 支持各种各样图表显示, 能想到的图表样式这里几乎都有, 图表还支持选择, 拖放和缩放动画效果 </td> 16.[ActionBarSherlock(不建议使用)](https://github.com/JakeWharton/ActionBarSherlock) <td width="275"> ActionBarSherlock 这个库是 JakeWharton 大神开发出来支持 Android3.0 以下版本的, 后来慢慢的 Google 也提供了 AppCompat 库来支持 Android3.0 以下版本使用 ActionBar, 因此作者不建议我们再使用这个库了 </td> 17. [androidannotations](https://github.com/excilys/androidannotations) <td width="275"> AndroidAnnotations 是一个能够让你快速进行 Android 开发的开源框架, 它能让你专注于真正重要的地方, 使代码更加精简, 使项目更加容易维护, 它的目标就是 &#8220;Fast Android Development.Easy maintainance&#8221; </td> 18. [ViewPagerIndicator](https://github.com/JakeWharton/ViewPagerIndicator) <td width="275"> 由 JakeWharton 大神开发出来的一个 ViewPager 指示器, 使用起来简单方便, 可高度定制, 开发出各种各样动画效果 </td> 19. [glide](https://github.com/bumptech/glide) <td width="275"> Glide 是 Google 员工的开源项目, 广泛应用于 Google 一些 App 上, 在2014年 Google I/O 大会上被推荐使用, Glide 和 Picasso 被人拿来比较研究过, Glide 与 Picasso 有 90% 的相似度, 但在一些细节上还是有点区别的, 各有各优缺点看君选择 </td> 20. [HomeMirror](https://github.com/HannahMitt/HomeMirror) <td width="275"> 开发者是由一名程序媛 Hannah Mittelstaedt , HomeMirror 是一款 Android 镜子应用, 目前它能实现日期, 时间, 天气, 生日信息, 事件提醒器, 骑车天气的推荐, 股票信息, XKCD 漫画网站的新帖等等 </td> 21. [Android-PullToRefresh(不建议使用)](https://github.com/chrisbanes/Android-PullToRefresh) <td width="275"> 一个强大的拉动刷新开源项目,支持各种控件下拉刷新,ListView、ViewPager、WebView、ExpandableListView、GridView、ScrollView、Horizontal ScrollView、Fragment 上下左右拉动刷新, 不过现在这个项目已经停止维护更新了, 推荐使用 Android-Ultra-Pull-to-Refresh </td> 22. [MaterialDesignLibrary](https://github.com/navasmdc/MaterialDesignLibrary) <td width="275"> 这个库控件都是遵循了 Google Material Design 设计规范开发出来, 例如有: Flat Button, Rectangle Button, CheckBox, Switch, Progress bar circular indeterminate 等等 </td> 23. [PhotoView](https://github.com/chrisbanes/PhotoView) <td width="275"> PhotoView 是 ImageView 的子类, 支持所有 ImageView 的源生行为, 例如: 支持 Pinch 手势自由缩放, 支持双击放大/还原, 支持平滑滚动等等, 并且非常方便的与 ImageLoader/Picasso 之类的网络图片读取库集成使用, 还方便的与 ViewPager 等同样支持滑动手势的控件集成 </td> 24. [RxAndroid](https://github.com/ReactiveX/RxAndroid) <td width="275"> 由 JakeWharton 大神主导开发的项目, RxAndroid 是 RxJava 的一个针对 Android 平台的扩展, 主要用于 Android 开发 </td> 25. [material-dialogs](https://github.com/afollestad/material-dialogs) <td width="275"> Material Dialogs 是一个可高度定制易用, 符合 Material Design 风格的 Dialogs, 兼容 Android API8 以上版本, 个人使用感觉它完全可替代 Android 原生那个, 比原生那个更加简单易用 </td> 26.[Android-ObservableScrollView](https://github.com/ksoichiro/Android-ObservableScrollView) <td width="275"> ObservableScrollView 是一款用于在滚动视图中观测滚动事件的 Android 库, 它能够轻而易举地与 Android 5.0 Lollipop 引进的工具栏 (Toolbar) 进行交互, 还可以帮助开发者实现拥有 Material Design 应用视觉体验的界面外观, 支持ListView, ScrollView, WebView, RecyclerView, GridView组件 </td> 27. [Android-Bootstrap](https://github.com/Bearded-Hen/Android-Bootstrap) <td width="275"> Android 版的 Bootstrap, 利用这个库能够实现很多 Bootstrap 样式风格, 之前有学过 Html 的人就知道 Bootstrap 是什么玩意啦 </td> 28. [AndroidSwipeLayout](https://github.com/daimajia/AndroidSwipeLayout) <td width="275"> 开发者是代码家, AndroidSwipeLayout 是一个支持ListView, GridView, ViewGroup等等左右上下滑动出操作菜单, 类似 qq 消息列表向左滑动显示出多某条信息的操作菜单 </td> 29. [dagger](https://github.com/square/dagger) <td width="275"> Dagger 是 Square 公司出品的一个针对 Android 和 Java 的快速依赖注入器, 能够有效减少你敲代码量 </td> 30. [ListViewAnimations](https://github.com/nhaarman/ListViewAnimations) <td width="275"> 一个轻轻松松给 Android ListView 添加动画效果的库, 支持的动画有: Alpha, SwingRightIn, SwingLeftIn, SwingBottomIn, SwingRightIn and ScaleIn等等, 使用它能很容易就实现帅爆的效果 </td> 31. [PagerSlidingTabStrip](https://github.com/astuetz/PagerSlidingTabStrip) <td width="275"> PagerSlidingTabStrip 是一个给 Android ViewPager添加上 ViewPager 滑动指示器, 从 GitHub 上面看, 这个库似乎没有人在维护了, 请谨慎使用该库 </td> 32. [AndroidViewAnimations](https://github.com/daimajia/AndroidViewAnimations) <td width="275"> 开发者是代码家, 这个库实现很多很酷炫的 Android 动画, 动画效果是借鉴 Animate.css 来实现的, 非常酷, 而且这个使用起来也是非常简单 </td> 33. [AndroidSlidingUpPanel](https://github.com/umano/AndroidSlidingUpPanel) <td width="275"> AndroidSlidingUpPanel 是一个上拉面板, 就是向上滑动的时候往上飞出一个显示面板控件, 该库效果在 Google Music, Google Maps and Rdio等 App 应用到 </td> 34. [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) <td width="275"> MaterialDrawer 是一个类似 Google 官方 NavigationView 侧滑显示控件, 个人认为 NavigationView 并没有 MaterialDrawer 实用, 因为 NavigationView 自由度不是很好, 很多都写死了不可以自由定义布局, 而 MaterialDrawer 能够实现跟 NavigationView 一样的效果, 同时还支持自定义效果, 自由度非常高 </td> 35. [Material-Animations](https://github.com/lgvalle/Material-Animations) <td width="275"> Material-Animations 是一个很好过渡动画库, 可以应用于 Activity 与 Activity 之间的跳转, Fragment 与 Fragment 之间的跳转, 以及各个 View 变化前后的过渡动画 </td> 36. [MaterialViewPager](https://github.com/florent37/MaterialViewPager) <td width="275"> 一个简单易用 Material Design 风格的 ViewPager 库 </td> 37. [ion](https://github.com/koush/ion) <td width="275"> ion 是一个让 Android 的网络操作变得极其简单, 支持异步获取和处理JSON, 支持 Android 文件下载 (同时支持下载进度条绑定), 支持安全链接和代理 </td> 38. [stetho](https://github.com/facebook/stetho) <td width="275"> Stetho是 Facebook 出品的一个强大的 Android 调试工具,使用该工具你可以在 Chrome Developer Tools查看App的布局, 网络请求(仅限使用Volley, okhttp的网络请求库), sqlite, preference, 一切都是可视化的操作,无须自己在去使用adb, 也不需要root你的设备 </td> 39. [fastjson](https://github.com/alibaba/fastjson) <td width="275"> Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景 </td> 40. [cardslib](https://github.com/gabrielemariotti/cardslib) <td width="275"> Cardslib 是早期由 Gabriele Mariotti 开发的一个为开发者方便实现各种 Card UI 的 Android 开源代码库, 后来 Google 官方提供自己封装了 CardView 在 v7 包下, 使用 Google 官方的可以完全替代了这个库, 因此这个也被弃用了 </td> 41. [Android-Ultra-Pull-To-Refresh](https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh) <td width="275"> 开发者是廖祜秋, 这个是一个非常强大的下拉刷新库, 继承 ViewGroup 可以包含任何 View, 功能甚至比 SwipeRefreshLayout 强大, 使用起来也非常容易, 还可以自由定制自己的 UI 样式 </td> 42. [greenDAO](https://github.com/greenrobot/greenDAO) <td width="275"> greenDAO 是一个可以帮助 Android 开发者快速将 Java 对象映射到 SQLite 数据库的表单中的 ORM解决方案, 通过使用一个简单的面向对象 API, 开发者可以对 Java 对象进行存储, 更新, 删除和查询, greenDAO 相对 OrmLite, AndrORM 这两个 ORM 开源库, 性能是最高的 </td> 43. [AndroidStaggeredGrid](https://github.com/etsy/AndroidStaggeredGrid) <td width="275"> AndroidStaggeredGrid 是一个支持多列并且每一行的 item 大小不一, 交错排列的 GridView, 就是实现瀑布流样式效果, 目前该库已经被弃用了, 开发者建议我们使用 Google 官方控件 RecyleView 中的 StaggeredGridLayoutManager 布局来实现瀑布流效果 </td> 44. [otto](https://github.com/square/otto) <td width="275"> Otto 是 Square 公司出的一个事件库 (pub/sub 模式), 用来简化应用程序组件之间的通讯, otto 修改自 Google 的 Guava 库, 专门为 Android 平台进行了优化, 与上面介绍的 EventBus 相比, 两个库各有各的优点, 完全取决于我们自己项目的需求来选择它们哪一个 </td> 45. [xUtils](https://github.com/wyouflf/xUtils) <td width="275"> xUtils 是一个快速开发框架, 里面包含 DbUtils, ViewUtils, HttpUtils, BitmapUtils 四大模块, 可用于快速开发, 支持大文件上传, 拥有更加灵活的 ORM, 最低兼容 Android 2.2 </td> 46. [realm-java](https://github.com/realm/realm-java) <td width="275"> Realm 一个轻量的 Android 版本的数据存储库, 比 Android 原生系统的 SQLite 更加简洁快速对数据进行操作 </td> 47.[Android-CleanArchitecture](https://github.com/android10/Android-CleanArchitecture) <td width="275"> CleanArchitecture 是一个非常典型使用 MVP 架构的项目, 大家如果还没有理解 MVP 架构的可以看看这个项目 </td> 48. [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) <td width="275"> StickyListHeaders 是一个实现能够固定在屏幕顶部的ListView Section Header库, 就是当前 section 的 header 固定在屏幕顶部, 当滑动到其他 section 时, 其他 section 的 header 会代替之前的 section 的 header, 固定到屏幕顶部, 类似于 Android4.0 的手机通讯录的效果 </td> 49. [AppIntro](https://github.com/PaoloRotolo/AppIntro) <td width="275"> AppIntro 是一个让人轻松快速搭建漂亮酷炫的引导页库 </td> 50. [ActiveAndroid](https://github.com/pardom/ActiveAndroid) <td width="275"> ActiveAndroid 是采用Rails中的 [Active Record](http://en.wikipedia.org/wiki/Object-relational_mapping)架构模式设计的适用于 Android 平台的轻量级 ORM 架构, 几乎可以不用写任何 SQL 代码实现快速开发 </td> 51. [android-volley](https://github.com/mcxiaoke/android-volley) <td width="275"> Volley 是谷歌官方开发团队在 2013 年 Google I/O 大会推出的一个新的网络通信框架, 这个框架把 AsyncHttpClient 和 Universal-Image-Loader 的优点集于了一身,既可以像AsyncHttpClient 一样非常简单地进行 HTTP 通信,也可以像 Universal-Image-Loader 一样轻松加载网络上的图片, 这个库并不是官方的, 只是托管同步在 Maven, 官方只提供的 Jar 包 </td> 52. [twoway-view](https://github.com/lucasr/twoway-view) <td width="275"> TwoWayView 是简化 RecyclerView 开发的一个库, 可以在其 Base LayoutManager 基础上构建各种各样的布局, 该库内置了几个常用布局 List, Grid, Staggered Grid,Spannable Grid </td> 53. [ShowcaseView](https://github.com/amlcurran/ShowcaseView) <td width="275"> ShowcaseView 是一个非常适合用于对用户进行第一次使用进行指导的库,使用起来非常简单还可以自定义样式 </td> 54. [Calligraphy](https://github.com/chrisjenx/Calligraphy) <td width="275"> Calligraphy 是一个用来简化 Android 应用使用自定义字体的类库, 该类库会自动查找应用中的 TextView 并设置其使用的字体 </td> 55. [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) <td width="275"> NineOldAndroids 由 JakeWharton 大神开发的一个向下兼容的动画库, 主要是使低于API 11的系统也能够使用 View 的属性动画, 不过现在 JakeWharton 大神已经不推荐使用该库, 而是推荐我们使用官方封装在 Support 库里面的动画 </td> 56. [android-floating-action-button](https://github.com/futuresimple/android-floating-action-button) <td width="275"> FloatingActionButton 是一个悬浮操作按钮, 官方在 Support Design 包下也有封装一个类似这个库效果的 FloatingActionButton, 值得说明的是这个库是早在官方封装之前就存在的, 个人感觉这个库比官方那个更加好用 </td> 57. [CircleImageView](https://github.com/hdodenhof/CircleImageView) <td width="275"> CircleImageView 是一个轻松帮你实现圆形效果 ImageView 图片库, CircleImageView 是基于 ImageView 扩展出来, 因此它拥有 ImageView 控件所有属性, 简单易用值得你使用的库 </td> 58. [material](https://github.com/rey5137/material) <td width="275"> Material 是将 Material Design 风格控件封装在该库当中, 目前封装有Progress, Button, Switch, Slider, Spinner, Text Field, TabPageIndicator, SnackBar, Dialog, BottomSheetDialog, Dynamic theme </td> 59. [ActionBar-PullToRefresh](https://github.com/chrisbanes/ActionBar-PullToRefresh) <td width="275"> ActionBar-PullToRefresh 是一个下拉刷新, 下拉刷新时在 ActionBar 出现加载中提示的库 </td> 60. [FloatingActionButton](https://github.com/makovkastar/FloatingActionButton) <td width="275"> 又一个悬浮操作按钮库, 该库添加支持监听滑滚动事件, 当向下滑时按钮隐藏, 向上滑时按钮显示, 还有动画效果, 支持监听 ListView, ScrollView, RecylerView </td> 61. [AndroidAsync](https://github.com/koush/AndroidAsync) <td width="275"> AndroidAsync 是一款基于 NIO 的低端 Android 异步 socket, http (client+server), websocket 和 socket.io 网络通信协议类库 </td> 62. [rebound](https://github.com/facebook/rebound) <td width="275"> Rebound 是 Facebook 推出的一个弹性动画库, 可以让动画看起来真实自然, 像真实世界的物理运动, 带有力的效果, 使用的参数则是 Facebook 的 origami 中使用的 </td> 63. [android-common](https://github.com/Trinea/android-common) <td width="275"> android-common-lib 是 Trinea 大神收集的一些开发通用的缓存, 公共 View 以及一些常用工具类 </td> 64. [RippleEffect](https://github.com/traex/RippleEffect) <td width="275"> RippleEffect 是一个实现在 Android 任何组件点击出现 Material Design 的波纹效果, 向下兼容到 Android API9 </td> 65. [SmoothProgressBar](https://github.com/castorflex/SmoothProgressBar) <td width="275"> SmoothProgressBar 是一个帮你的 App 方便实现可定制, 平滑动画的水平滚动进度条库 </td> 66. [recyclerview-animators](https://github.com/wasabeef/recyclerview-animators) <td width="275"> RecyclerView Animators 是一个对 Recycler 控件的 Item 添加以及删除增加动画效果, 动画效果有Scale, Fade, Flip, Slide 里面各种各样效果 </td> 67. [circular-progress-button](https://github.com/dmytrodanylyk/circular-progress-button) <td width="275"> 一个带进度显示的 Button, 效果和动画做的都非常赞 </td> 68. [DroidPlugin](https://github.com/Qihoo360/DroidPlugin) <td width="275"> DroidPlugin 是 360 手机助手在 Android 系统上实现了一种新的插件机制: 它可以在无需安装, 修改的情况下运行APK文件, 此机制对改进大型APP的架构, 实现多团队协作开发具有一定的好处 </td> 69. [dynamic-load-apk](https://github.com/singwhatiwanna/dynamic-load-apk) <td width="275"> 开发者是singwhatiwanna(任玉刚), 是《Android 开发艺术探索》书籍的作者, 这个是作者联合另两位开发者啸(时之沙)和宋思宇花了几个月时间研究出来的 Apk 动态加载框架, 想了解更多关于这框架可到作者博客看 [这篇文章](http://blog.csdn.net/singwhatiwanna/article/details/39937639) 有详细介绍 </td> 70. [ExoPlayer](https://github.com/google/ExoPlayer) <td width="275"> ExoPlayer 是Google 开发团队开源出来的一个媒体播放库, 比 Android 框架原生的 MediaPlayer 拥有更多优点支持动态的自适应流 HTTP(DASH) 和 平滑流, 支持高级的HLS特性, 支持自定义和扩治你的使用场景等等 </td> 71. [Crouton](https://github.com/keyboardsurfer/Crouton) <td width="275"> Crouton 是一个显示提示信息的显示工具类, 可以用来代替Toast, 默认显示在窗口的顶部, 可以按队列一个接着一个显示, 不过该库已经被弃用, 不推荐使用 </td> 72. [robospice](https://github.com/stephanenicolas/robospice) <td width="275"> RoboSpice 是一个使你建立异步的长时间的运行任务异常轻松的一个网络库,在网络请求,缓存支持,和提供开箱即用的rest请求方面尤为强大 </td> 73. [hugo](https://github.com/JakeWharton/hugo) <td width="275"> Hugo 是 JakeWharton 大神推出的一个用于打印 Log, hugo 是基于注解被调用的, 引入相关依赖后, 在方法上加上 @DebugLog 即可输出 Log, 使用非常简单 </td> 74. [async-http-client](https://github.com/AsyncHttpClient/async-http-client) <td width="275"> AsyncHttpClient 是又一款 Android 异步请求库, 该库支持 WebSocket 协议, 使用起来也比较简单易用 </td> 75. [UltimateRecyclerView](https://github.com/cymcsg/UltimateRecyclerView) <td width="275"> UltimateRecyclerView 是一个功能强大的 RecyclerView(advanced and flexible version of ListView), 包括了下拉刷新, 加载更多, 多种动画, 空数据提示, 拖动排序, 视差处理, 工具栏渐变, 滑动删除, 自定义floating button, 多种刷新效果, scrollbar, sticky header, 多 layout 支持等等元素, 而且使用起来跟 RecyclerView 一样的方便 </td> 76. [MaterialEditText](https://github.com/rengwuxian/MaterialEditText) <td width="275"> MaterialEditText 是就职于 Flipboard 的员工 [扔物线](https://www.zhihu.com/people/rengwuxian) 开发的, 在 AppCompat v21 中也提供了 Material Design 的控件 EditText, 可是由于比较难用, 没有提供设置颜色的 Api, 于是就产生这个第三方库 </td> 77. [Side-Menu.Android](https://github.com/Yalantis/Side-Menu.Android) <td width="275"> Side Menu 是 [Yalantis](https://yalantis.com/) 组织开源出来, 该组织因开源出一些动画很棒的开源库为大家所熟知该库是其中一个, 该库是提供翻页动画效果的侧边菜单, 动画体验超赞的 </td> 78. [drag-sort-listview](https://github.com/bauerca/drag-sort-listview) <td width="275"> DragSortListView 是一个可以实现拖动排序, 滑动删除的 listview 控件, 注意的是作者对该库已经放弃维护更新了, 不过感兴趣的人可以去研究一下 </td> 79. [android-times-square](https://github.com/square/android-times-square) <td width="275"> TimesSquare 是 Square 公司出品的一款显示日历选择日期的控件, 可以让用户选择多个日期 </td> 80. [GreenDroid(不建议使用)](https://github.com/cyrilmottier/GreenDroid) <td width="275"> GreenDroid 是一个封装好的 Android UI 界面库, 不过该库已经被弃用了,不建议使用 </td> 81. [logger](https://github.com/orhanobut/logger) <td width="275"> Logger 是一个简单, 漂亮, 强大 Android 打印日志库 </td> 82. [acra](https://github.com/ACRA/acra) <td width="275"> Acra 是一个能够让 Android 应用自动将崩溃报告以谷歌文档电子表的形式进行发送的库, 旨在当应用发生崩溃或出现错误行为时, 开发者可以获取到相关数据 </td> 83. [FadingActionBar](https://github.com/ManuelPeinado/FadingActionBar) <td width="275"> FadingActionBar 是一个支持 ListView, ScrollView, WebView 向下滚动时逐渐显示 ActionBar 库 </td> 84. [AndroidImageSlider](https://github.com/daimajia/AndroidImageSlider) <td width="275"> AndroidImageSlider 库开发者是代码家, 该库是为 Banner 图片滑动提供多种动画效果, 还可以轻易为 Banner 加载网络图片 </td> 85. [SystemBarTint](https://github.com/jgilfelt/SystemBarTint) <td width="275"> SystemBarTint 是一个实现沉浸式状态栏库, 适用于 Android 系统 4.4 其以上的版本 </td> 86. [android-menudrawer](https://github.com/SimonVT/android-menudrawer) <td width="275"> MenuDrawer 是一款滑出式菜单库, 通过拖动屏幕边缘滑出菜单, 支持屏幕上下左右划出, 支持当前 View 处于上下层, 支持 Windows 边缘, ListView 边缘, ViewPager 变化划出菜单等 </td> 87. [RoundedImageView](https://github.com/vinc3m1/RoundedImageView) <td width="275"> RoundedImageView 一个快速支持图片圆角显示效果的库, 该库特点是能快速加载, 为了提高加载速度, 该库不用创建原始位图的副本, 不使用clipPath, 不使用 setXfermode 裁剪的位图等方式来实现 ImageView 圆角, 使用也非常简单 </td> 88. [afinal](https://github.com/yangfuhai/afinal) <td width="275"> Afinal 是一个 android 的 sqlite orm 和 ioc 框架, 同时封装了 android 中的 http 框架, 使其更加简单易用, 使用 finalBitmap, 无需考虑 bitmap 在 android 中加载的时候 oom 的问题和快速滑动的时候图片加载位置错位等问题, Afinal 的宗旨是简洁, 快速, 约定大于配置的方式, 尽量一行代码完成所有事情 </td> 89. [android-pulltorefresh(不建议使用)](https://github.com/johannilsson/android-pulltorefresh) <td width="275"> 另一个下拉刷新库, 但是该库已经停止维护, 因此不建议使用, 推荐使用 Android-Ultra-Pull-to-Refresh </td> 90. [Bolts-Android](https://github.com/BoltsFramework/Bolts-Android) <td width="275"> Bolts 是一款底层类库集合, 在后台实现异步操作, 并提供接口反馈当前异步执行的程度 (可以通过接口实现UI进度更新), 最后反馈执行的结果给UI主线程, 与AsyncTask比较: (1)使用的是无大小限制的线程池; (2)任务可组合可级联,防止了代码耦合 </td> 91. [NumberProgressBar](https://github.com/daimajia/NumberProgressBar) <td width="275"> NumberProgressBar 开发者是代码家, 这是一个带简约性感数字显示的进度条库, 使用非常简单方便 </td> 92. [SwipeBackLayout](https://github.com/ikew0ng/SwipeBackLayout) <td width="275"> SwipeBackLayout 是一个支持屏幕上下左右滑动返回上层 Activity, 关闭当前 Activity, 类似简书 App </td> 93. [android-gif-drawable](https://github.com/koral--/android-gif-drawable) <td width="275"> 一个支持 gif 显示的 view, 用 jni 实现的, 编译生成 so 库后直接 xml 定义 view 即可, 简单易用 </td> 94. [VitamioBundle](https://github.com/yixia/VitamioBundle) <td width="275"> Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架, 特点:(1) 全面支持硬件解码与 GPU 渲染, (2) 能够流畅播放 720P 甚至 1080P 高清 MKV, FLV, MP4, MOV, TS, RMVB 等常见格式的视频, (3) 在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP, HLS(m3u8)等常见的多种视频流媒体协议, 包括点播与直播 </td> 95. [SmartTabLayout](https://github.com/ogaclejapan/SmartTabLayout) <td width="275"> SmartTabLayout 是一个自定义的 Tab title strip, 基于 Google Samples 中的 android-SlidingTabBasic 项目, 滑动时 Indicator 可平滑过渡 </td> 96. [uCrop](https://github.com/Yalantis/uCrop) <td width="275"> uCrop 是[Yalantis](https://yalantis.com/) 组织开源的图片裁剪库, 支持缩放, 旋转图片, 支持各种比例的裁剪框, 非常强大的一个图片裁剪库 </td> 97. [android-crop](https://github.com/jdamcd/android-crop) <td width="275"> 又一个图片裁剪库, 向下兼容到 Api 10, 个人感觉这个库并没有比上面介绍的 uCrop 强大 </td> 98. [HoloEveryWhere](https://github.com/Prototik/HoloEverywhere) <td width="275"> HoloEveryWhere 是一套 Android 开发库, 提供了全套 Holo Style 控件, 它的外观与功能和标准 Holo Style 控件基本相同, 唯一不同的是它可以运行在低于 4.0 版本的 Android 系统上 </td> 99. [AVLoadingIndicatorView](https://github.com/81813780/AVLoadingIndicatorView) <td width="275"> AVLoadingIndicatorView 库含有各种各样漂亮的加载动画效果, 使用起来也非常简单, 和平时使用 ProgressBar 一样 </td> 00. [sweet-alert-dialog](https://github.com/pedant/sweet-alert-dialog) <td width="275"> Android 版的 SweetAlert, 清新文艺, 快意灵动的甜心弹框, 灵感来源于 JS 版[SweetAlert](http://t4t5.github.io/sweetalert/) </td> {#user-content-粗计.anchor}粗计 {#user-content-square-公司占有-7-席.anchor}Square 公司占有 7 席 项目名称 <th> 排名 </th> [Retrofit](https://github.com/square/retrofit) <td width="130"> 4 </td> [OkHttp](https://github.com/square/okhttp) <td width="130"> 5 </td> [Picasso](https://github.com/square/picasso) <td width="130"> 7 </td> [LeakCanary](https://github.com/square/leakcanary) <td width="130"> 13 </td> [Dagger](https://github.com/square/dagger) <td width="130"> 29 </td> [Otto](https://github.com/square/otto) <td width="130"> 44 </td> [TimesSquare](https://github.com/square/android-times-square) <td width="130"> 79 </td> {#user-content-facebook-公司占有-4-席.anchor}FaceBook 公司占有 4 席 项目名称 <th> 排名 </th> [React Native](https://github.com/facebook/react-native) <td width="124"> 1 </td> [Fresco](https://github.com/facebook/fresco) <td width="124"> 11 </td> [Stetho](https://github.com/facebook/stetho) <td width="124"> 38 </td> [Rebound](https://github.com/facebook/rebound) <td width="124"> 62 </td> {#user-content-jakewharton-大神占有-5-席.anchor}JakeWharton 大神占有 5 席 项目名称 <th> 排名 </th> [Butter Knife](https://github.com/JakeWharton/butterknife) <td width="98"> 14 </td> [ActionBarSherlock](https://github.com/JakeWharton/ActionBarSherlock) <td width="98"> 16 </td> [ViewPagerIndicator](https://github.com/JakeWharton/ViewPagerIndicator) <td width="98"> 18 </td> [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) <td width="98"> 55 </td> [Hugo](https://github.com/JakeWharton/hugo) <td width="98"> 73 </td> {#user-content-代码家大神占有-4-席.anchor}代码家大神占有 4 席 项目名称 <th> 排名 </th> [AndroidSwipeLayout](https://github.com/daimajia/AndroidSwipeLayout) <td width="89"> 28 </td> [AndroidViewAnimations](https://github.com/daimajia/AndroidViewAnimations) <td width="89"> 32 </td> [AndroidImageSlide](https://github.com/daimajia/AndroidImageSlider) <td width="89"> 84 </td> [NumberProgressBar](https://github.com/daimajia/NumberProgressBar) <td width="89"> 91 </td> 转自:http://www.lesscode.cn/index.php?s=/view-index-id-299.shtml ...

2016年3月15日 · 9 分钟 · 天边的星星

这可能是目前最鲁棒的Android声音录制和播放封装库了

安卓开发过程中一旦开始和硬件打交道,以及涉及到一定的native代码之后,各种闪退就开始浮出水面了,声音录制和播放当然不例外。本文总结了YOLO安卓客户端大半年来的安卓音频实践,整理出一套系统API的封装,命名为RxAndroidAudio。 概览 安卓平台和声音录制与播放相关的主要是4个类:MediaRecorder,MediaPlayer,AudioRecord和AudioTrack。 MediaRecorder可以录制视频和音频到文件,MediaPlayer可以播放视频和音频文件,AudioRecord可以提供接口读取音频流数据(byte数组或者short数组),AudioTrack提供接口用于播放音频流数据。 小结一下,其中MediaRecorder和AudioRecord用于声音录制,MediaPlayer和AudioTrack用于声音播放。AudioRecord和AudioTrack用于操作音频流数据,操作对象是byte数组(或者short数组),而MediaRecorder和MediaPlayer提供了经过更高层抽象和封装接口,直接对文件进行操作,而且他俩功能更丰富,同时支持音频和视频。 本文会涉及到部分关于声音录制和播放更底层的实现,详细的分析并不是本文的内容范围了,此外本文主要目标并不是声音录制和播放的使用教程,本文主要关注的是上述4个类的使用过程中需要注意的地方。 基于文件的操作 使用MediaRecorder录制声音到文件: mRecorder.prepare()调用需要捕获IOException和RuntimeException,注意需要捕获RuntimeException而不是IllegalStateException,尽管Java doc中只声明了会抛出IllegalStateException,但是查看jni层代码可以看到,prepare的调用也是可能会触发RuntimeException的; mRecorder.start(),mRecorder.stop(),mRecorder.reset()调用也需要捕获RuntimeException,理由同上; 无论是prepare还是start,抛出异常之后都需要reset和release; 需要保证不会对jni层进行多线程的调用,以免出现下面这样的“静默闪退”(参考资料),RxAndroidAudio通过单例和synchronized方法来保证这一点: A/libc: Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 9302 (RxComputationTh) 当用户录完声音,需要停止录音,调用stop的时候,需要sleep一段时间,以免最后几百毫秒录不上,这有可能是安卓系统音频编码器的bug,参考资料; 当prepare返回后,有些低端的设备需要再延迟一段时间开始说话,以免开头几百毫秒录不上,可以在prepare返回后延迟几百毫秒(例如300ms)再显示初始化完毕的UI,原因还需要继续寻找; 使用MediaPlayer播放声音文件: 和MediaRecorder一样,prepare,start,stop,reset,release函数的调用都需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; MediaPlayer提供了两种音频文件播放方式:通过文件绝对路径指定播放文件,或者使用资源文件id指定;绝对路径的方式需要调用mPlayer.prepare(),而资源文件id方式不需要; 在MediaPlayer.OnCompletionListener的onCompletion回调中,需要延迟一定时间再释放MediaPlayer,否则可能导致下次紧接着的播放无法成功(静默失败,不会抛出异常),原因还需要继续寻找; 基于数据流的操作 使用AudioRecord录制音频流数据: 和MediaRecorder一样,startRecording需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; mAudioRecord.read的返回值需要进行错误检查; mAudioRecord.read传入的参数类型需要进行区分,ENCODING_PCM_16BIT格式的录音需要传入short数组,ENCODING_PCM_8BIT格式的录音需要传入byte数组,尽管在jni层的实现都是一样的,但是[Java doc][18]明确说明了这一注意事项,理应遵循; RxAndroidAudio使用ExecutorService来执行异步任务(从AudioRecord中循环读取数据); [使用AudioTrack播放音频流数据][19]: 和MediaRecorder一样,write需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; Bonus Part Reactive! RxAndroidAudio之所以叫Rx,就是因为它尽可能的提供了Reactive的API。 RxAudioPlayer播放声音文件: 当然RxAudioPlayer也提供了传统的API: RxAmplitude获取当前说话音量等级: 当然RxAmplitude使用的是AudioRecorder的传统API: [18]: http://developer.android.com/reference/android/media/AudioRecord.html#read(byte[], int, int) [19]: https://github.com/Piasy/RxAndroidAudio/blob/master/rxandroidaudio%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgithub%2Fpiasy%2Frxandroidaudio%2FStreamAudioPlayer.java

2016年2月26日 · 1 分钟 · 天边的星星

国内镜像加速Android源码下载

转发:http://www.tuicool.com/articles/nmy26nv 清华大学镜像 无论是Ubuntu源更新还是Android源码下砸,都是使用清华大学镜像。 Ubuntu源使用方法 不多说了,不会的自行Google。 Android源码清华镜像使用方法 官方介绍使用方法 ==== 点击浏览 ==== 我来介绍 1.下载修改好的 repo , ==== 下载地址 ====,密码: rb5t ; 2.打开终端,输入: ``` mkdir ~/bin PATH=~/bin:$PATH </div> </div> 3.将 **repo** 放入 `~/bin` 目录下; 4.赋予执行权限,终端输入: <div> <div> ``` chmod a+x ~<span class="regexp">/bin/repo</span> 5.建立android源码存放目录: ``` mkdir android_source cd android_source </div> </div> 6.查看想要下载的源码的Tag和Builds,网址: [==== **点击查看,需要翻蔷** ====](https://source.android.com/source/build-numbers.html#source-code-tags-and-builds),这里 @安卓猴 给你们截下图,自己放大查看: ![](http://img1.tuicool.com/bMBn2eu.jpg!web) 7.例如我要下载android-5.1.1_r3,就在终端输入: <div> <div> ``` repo init -u <span class="symbol">git:</span>/<span class="regexp">/aosp.tuna.tsinghua.edu.cn/android</span><span class="regexp">/platform/manifest</span> -b android-<span class="number">5.1</span>.<span class="number">1_</span>r3 8.终端输入下面命令使用 repo 开始源代码下载同步, -j4 表示并发数为4,清华镜像只支持最大并发数4: ...

2016年2月21日 · 1 分钟 · 天边的星星

Android 自定义控件——图片剪裁

该控件由另一篇文章:Android 图片拖拽、放大缩小的自定义控件 扩展而来 http://www.linuxidc.com/Linux/2014-12/110763.htm 如图: 思路:在一个自定义View上绘制一张图片(参照前面提到的另一篇文章),在该自定义View上绘制一个自定义的FloatDrawable,也就是图中的浮层。绘制图片和FloatDrawable的交集的补集部分灰色阴影(这个其实很简单,就一句话)。在自定义View的touch中去处理具体的拖动事件和FloatDrawable的变换。图片的绘制和FloatDrawable的绘制以及变换最终其实就是在操作各自的Rect而已,Rect就是一个有矩形,有四个坐标,图片和FloatDrawable就是按照坐标去绘制的。 CropImageView.java 该类继承View 功能:在onDraw方法中画图片、浮层,处理touch事件,最后根据坐标对图片进行剪裁。 public class CropImageView extends View { // 在touch重要用到的点, private float mX_1 = 0; private float mY_1 = 0; // 触摸事件判断 private final int STATUS_SINGLE = 1; private final int STATUS_MULTI_START = 2; private final int STATUS_MULTI_TOUCHING = 3; // 当前状态 private int mStatus = STATUS_SINGLE; // 默认裁剪的宽高 private int cropWidth; private int cropHeight; // 浮层Drawable的四个点 private final int EDGE_LT = 1; private final int EDGE_RT = 2; private final int EDGE_LB = 3; private final int EDGE_RB = 4; private final int EDGE_MOVE_IN = 5; private final int EDGE_MOVE_OUT = 6; private final int EDGE_NONE = 7; ...

2016年2月19日 · 7 分钟 · 天边的星星

Android ImageCropper 矩形 圆形 裁剪框

支持圆形裁剪框,裁剪后生成圆形图案。 代码基于开源项目修改,github上项目链接:https://github.com/shengge/android-crop 还是贴下效果图: 说一下圆形裁剪实现部分: 1.UI方面,自定义CircleHighlightView继承至HighlightView(原有的矩形裁剪框实现),直接看draw方法实现 **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#) [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#) <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> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> draw(Canvas canvas) { - canvas.save(); - Path path = <span class="keyword">new</span> Path(); - outlinePaint.setStrokeWidth( outlineWidth); - <span class="keyword">if</span>(!hasFocus()) {<span class="comment">//没焦点是,直接画一个黑色的矩形框</span> - outlinePaint.setColor( Color.BLACK); - canvas.drawRect( drawRect, outlinePaint); - } - <span class="keyword">else</span> { - Rect viewDrawingRect = <span class="keyword">new</span> Rect(); - viewContext.getDrawingRect( viewDrawingRect); - - <span class="comment">//已裁剪框drawRect,算出圆的半径</span> - <span class="comment">//添加一个圆形</span> - path.addCircle( drawRect.left + radius, drawRect.top + radius, radius, Direction.CW); - outlinePaint.setColor( highlightColor); - - <span class="comment">//裁剪画布,path之外的区域,以outsidePaint填充</span> - canvas.clipPath( path, Region.Op.DIFFERENCE); - canvas.drawRect( viewDrawingRect, outsidePaint); - - canvas.restore(); - <span class="comment">//绘制圆上高亮线,这里outlinePaint定义的Paint.Style.STROKE:表示只绘制几何图形的轮廓。</span> - canvas.drawPath( path, outlinePaint); - - <span class="comment">//当modifyMode为grow时,绘制handles,也就是那四个小圆</span> - <span class="keyword">if</span>(handleMode == HandleMode.Always || (handleMode == HandleMode.Changing && modifyMode == ModifyMode.Grow)) { - drawHandles( canvas); - } - } - } </div> 这里就实现了画圆形裁剪框的操作。 ### <a name="t1"></a>2. 响应和处理用户触摸事件 #### <a name="t2"></a>1). 判断触摸点坐标与圆的位置 <div> </div> <div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span> <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> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> - <span class="comment">/**</span> - <span class="comment"> * 根据x,y坐标,计算其与圆的关系(圆上、圆内、圆外)</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">int</span> getHitOnCircle(<span class="keyword">float</span> x, <span class="keyword">float</span> y) { - Rect r = computeLayout(); - <span class="keyword">int</span> retval = GROW_NONE; - <span class="keyword">final</span> <span class="keyword">float</span> hysteresis = 20F; - - <span class="keyword">int</span> centerX = r.left + radius; - <span class="keyword">int</span> centerY = r.top + radius; - - <span class="comment">//判断触摸位置是否在圆上</span> - <span class="keyword">double</span> rRadius = Math.sqrt( ret); - - <span class="keyword">if</span>(gap <= hysteresis) {<span class="comment">// 圆上。这里由于是继承至HighlightView(绘制矩形框的)来处理,所以模拟返回了左右上下,而非纯圆上,亲测可用。你也可以自定义。</span> - <span class="keyword">if</span>(x < centerX) {<span class="comment">// left</span> - retval |= GROW_LEFT_EDGE; - } - <span class="keyword">else</span> { - retval |= GROW_RIGHT_EDGE; - } - - <span class="keyword">if</span>(y < centerY) {<span class="comment">// up</span> - retval |= GROW_TOP_EDGE; - } - <span class="keyword">else</span> { - retval |= GROW_BOTTOM_EDGE; - } - } - <span class="keyword">else</span> <span class="keyword">if</span>(rRadius > radius) {<span class="comment">// outside</span> - retval = GROW_NONE; - } - <span class="keyword">else</span> <span class="keyword">if</span>(rRadius < radius) {<span class="comment">// inside,圆内就执行move</span> - retval = MOVE; - } - - <span class="keyword">return</span> retval; - } </div> 由于是继承至HighLightView(矩形框)来实现的,如果点(x,y)位置圆上,还需判断其它那个象限,对应矩形的上下左右位置。 <div> </div> #### <a name="t3"></a>2). 移动裁剪框 <div> 若上一步判断,触摸点在圆内,就会返回MOVE,并处理移动过程。 </div> <div> </div> <div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span> <div> <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> - <span class="comment">// Grows the cropping rectangle by (dx, dy) in image space</span> - <span class="keyword">void</span> moveBy(<span class="keyword">float</span> dx, <span class="keyword">float</span> dy) { - Rect invalRect = <span class="keyword">new</span> Rect(drawRect); - <span class="comment">//移动</span> - cropRect.offset(dx, dy); - - <span class="comment">// Put the cropping rectangle inside image rectangle</span> - cropRect.offset( - - cropRect.offset( - - drawRect = computeLayout(); - invalRect.union(drawRect); - invalRect.inset(-(<span class="keyword">int</span>) handleRadius, -(<span class="keyword">int</span>) handleRadius); - viewContext.invalidate(invalRect); - } </div> 移动裁剪框并保证其它image图片显示范围内。 <div> </div> #### <a name="t4"></a>3). 缩放裁剪框 <div> 此过程和上一步类似,将cropRect矩阵进行等比缩放即可,这里就细说了,详见代码:HighLightView.growBy(float dx, float dy) </div> <div> </div> ### <a name="t5"></a>3.将裁剪图片保存为圆形 <div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span> <div> <embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> - <span class="comment">/**</span> - <span class="comment"> * @param bitmap src图片</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">static</span> Bitmap getCircleBitmap(Bitmap bitmap) { - Bitmap output = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = <span class="keyword">new</span> Canvas( output); - - <span class="keyword">final</span> <span class="keyword">int</span> color = <span class="number">0xff424242</span>; - <span class="keyword">final</span> Paint paint = <span class="keyword">new</span> Paint(); - <span class="keyword">final</span> Rect rect = <span class="keyword">new</span> Rect( <span class="number"></span>, <span class="number"></span>, bitmap.getWidth(), bitmap.getHeight()); - - paint.setAntiAlias( <span class="keyword">true</span>); - paint.setFilterBitmap( <span class="keyword">true</span>); - paint.setDither( <span class="keyword">true</span>); - canvas.drawARGB( <span class="number"></span>, <span class="number"></span>, <span class="number"></span>, <span class="number"></span>); - paint.setColor( color); - <span class="comment">//在画布上绘制一个圆</span> - canvas.drawCircle( bitmap.getWidth() / <span class="number">2</span>, bitmap.getHeight() / <span class="number">2</span>, bitmap.getWidth() / <span class="number">2</span>, paint); - paint.setXfermode( <span class="keyword">new</span> PorterDuffXfermode( Mode.SRC_IN)); - canvas.drawBitmap( bitmap, rect, rect, paint); - <span class="keyword">return</span> output; - } </div> 注意:将bitmap保存为file时,格式请选择png,不然会出现黑色背景。 <div> </div> <div> 鉴于水平有限,从小语文就没学好,描述比较凌乱,需要深入理解的请阅读[源代码](http://download.csdn.net/detail/jiantao_yang/8433015)。 </div> <div> </div> <div> 附:另外一个很好开源项目 https://github.com/edmodo/cropper </div>

2016年2月19日 · 4 分钟 · 天边的星星

Android自定义相机拍照、图片裁剪的实现

最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类似于小猿搜题、学霸君等app。 其实Android提供Intent让我们打开系统的相机,但是系统相机跟自己app风格不搭,而且用起来体验不好。所以我使用了SDK提供的camera API自定义了一个相机,并且在相机界面上面添加了参考线,有助于用户将题目拍正,提高ocr的识别率。 1、绘制参考线的代码 ![复制代码](http://common.cnblogs.com/images/copycode.gif) 1 public class ReferenceLine extends View { 2 3 private Paint mLinePaint; 4 5 public ReferenceLine(Context context) { 6 super(context); 7 init(); 8 } 9 10 public ReferenceLine(Context context, AttributeSet attrs) { 11 super(context, attrs); 12 init(); 13 } 14 15 public ReferenceLine(Context context, AttributeSet attrs, int defStyleAttr) { 16 super(context, attrs, defStyleAttr); 17 init(); 18 } 19 20 private void init() { 21 mLinePaint = new Paint(); 22 mLinePaint.setAntiAlias(true); 23 mLinePaint.setColor(Color.parseColor("#45e0e0e0")); 24 mLinePaint.setStrokeWidth(1); 25 } 26 27 28 29 @Override 30 protected void onDraw(Canvas canvas) { 31 int screenWidth = Utils.getScreenWH(getContext()).widthPixels; 32 int screenHeight = Utils.getScreenWH(getContext()).heightPixels; 33 34 int width = screenWidth/3; 35 int height = screenHeight/3; 36 37 for (int i = width, j = 0;i &lt; screenWidth && j&lt;2;i += width, j++) { 38 canvas.drawLine(i, 0, i, screenHeight, mLinePaint); 39 } 40 for (int j = height,i = 0;j &lt; screenHeight && i &lt; 2;j += height,i++) { 41 canvas.drawLine(0, j, screenWidth, j, mLinePaint); 42 } 43 } 44 45 46 } ![复制代码](http://common.cnblogs.com/images/copycode.gif) ...

2016年2月19日 · 13 分钟 · 天边的星星

给 Android 开发者的 RxJava 详解

前言 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 。而最近这几个月,我也发现国内越来越多的人开始提及 RxJava 。有人说『RxJava 真是太好用了』,有人说『RxJava 真是太难用了』,另外更多的人表示:我真的百度了也谷歌了,但我还是想问: RxJava 到底是什么? 鉴于 RxJava 目前这种既火爆又神秘的现状,而我又在一年的使用过程中对 RxJava 有了一些理解,我决定写下这篇文章来对 RxJava 做一个相对详细的、针对 Android 开发者的介绍。 这篇文章的目的有两个: 给对 RxJava 感兴趣的人一些入门的指引 给正在使用 RxJava 但仍然心存疑惑的人一些更深入的解析 - [RxJava 到底是什么](http://gank.io/post/560e15be2dca930e00da1083#toc_1) - [RxJava 好在哪](http://gank.io/post/560e15be2dca930e00da1083#toc_2) - [API 介绍和原理简析](http://gank.io/post/560e15be2dca930e00da1083#toc_3) - [1. 概念:扩展的观察者模式](http://gank.io/post/560e15be2dca930e00da1083#toc_4) - [观察者模式](http://gank.io/post/560e15be2dca930e00da1083#toc_5) - [RxJava 的观察者模式](http://gank.io/post/560e15be2dca930e00da1083#toc_6) - [2. 基本实现](http://gank.io/post/560e15be2dca930e00da1083#toc_7) - [1) 创建 Observer](http://gank.io/post/560e15be2dca930e00da1083#toc_8) - [2) 创建 Observable](http://gank.io/post/560e15be2dca930e00da1083#toc_9) - [3) Subscribe (订阅)](http://gank.io/post/560e15be2dca930e00da1083#toc_10) - [4) 场景示例](http://gank.io/post/560e15be2dca930e00da1083#toc_11) - [a. 打印字符串数组](http://gank.io/post/560e15be2dca930e00da1083#toc_12) - [b. 由 id 取得图片并显示](http://gank.io/post/560e15be2dca930e00da1083#toc_13) - [3. 线程控制 —— Scheduler (一)](http://gank.io/post/560e15be2dca930e00da1083#toc_14) - [1) Scheduler 的 API (一)](http://gank.io/post/560e15be2dca930e00da1083#toc_15) - [2) Scheduler 的原理 (一)](http://gank.io/post/560e15be2dca930e00da1083#toc_16) - [4. 变换](http://gank.io/post/560e15be2dca930e00da1083#toc_17) - [1) API](http://gank.io/post/560e15be2dca930e00da1083#toc_18) - [2) 变换的原理:lift()](http://gank.io/post/560e15be2dca930e00da1083#toc_19) - [3) compose: 对 Observable 整体的变换](http://gank.io/post/560e15be2dca930e00da1083#toc_20) - [5. 线程控制:Scheduler (二)](http://gank.io/post/560e15be2dca930e00da1083#toc_21) - [1) Scheduler 的 API (二)](http://gank.io/post/560e15be2dca930e00da1083#toc_22) - [2) Scheduler 的原理(二)](http://gank.io/post/560e15be2dca930e00da1083#toc_23) - [3) 延伸:doOnSubscribe()](http://gank.io/post/560e15be2dca930e00da1083#toc_24) - [RxJava 的适用场景和使用方式](http://gank.io/post/560e15be2dca930e00da1083#toc_25) - [1. 与 Retrofit 的结合](http://gank.io/post/560e15be2dca930e00da1083#toc_26) - [2. RxBinding](http://gank.io/post/560e15be2dca930e00da1083#toc_27) - [3. 各种异步操作](http://gank.io/post/560e15be2dca930e00da1083#toc_28) - [4. RxBus](http://gank.io/post/560e15be2dca930e00da1083#toc_29) - [最后](http://gank.io/post/560e15be2dca930e00da1083#toc_30) - [关于作者:](http://gank.io/post/560e15be2dca930e00da1083#toc_31) - [为什么写这个?](http://gank.io/post/560e15be2dca930e00da1083#toc_32) 在正文开始之前的最后,放上 GitHub 链接和引入依赖的 gradle 代码: Github: https://github.com/ReactiveX/RxJava https://github.com/ReactiveX/RxAndroid 引入依赖: compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' (版本号是文章发布时的最新稳定版) ...

2016年1月20日 · 25 分钟 · 天边的星星

Android性能优化典范 – 第4季

Android性能优化典范第4季的课程学习笔记终于在2015年的最后一天完成了,文章共17个段落,包含的内容大致有:优化网络请求的行为,优化安装包的资源文件,优化数据传输的效率,性能优化的几大基础原理等等。因为学习认知水平有限,肯定存在不少理解偏差甚至错误的地方,请多多交流指正! 1)Cachematters for networking 想要使得Android系统上的网络访问操作更加的高效就必须做好网络数据的缓存。这是提高网络访问性能最基础的步骤之一。从手机的缓存中直接读取数据肯定比从网络上获取数据要更加的便捷高效,特别是对于那些会被频繁访问到的数据,需要把这些数据缓存到设备上,以便更加快速的进行访问。 Android系统上关于网络请求的Http Response Cache是默认关闭的,这样会导致每次即使请求的数据内容是一样的也会需要重复被调用执行,效率低下。我们可以通过下面的代码示例开启HttpResponseCache。 开启Http Response Cache之后,Http操作相关的返回数据就会缓存到文件系统上,不仅仅是主程序自己编写的网络请求相关的数据会被缓存,另外引入的library库中的网络相关的请求数据也会被缓存到这个Cache中。 网络请求的场景有可以是普通的http请求,也可以打开某个URL去获取数据,如下图所示: 我们有两种方式来清除HttpResponseCache的缓存数据:第一种方式是缓存溢出的时候删除最旧最老的文件,第二种方式是通过Http返回Header中的Cache-Control字段来进行控制的。如下图所示: 通常来说,HttpResponseCache会缓存所有的返回信息,包括实际的数据与Header的部分.一般情况下,这个Cache会自动根据协议返回Cache-Control的内容与当前缓存的数据量来决定哪些数据应该继续保留,哪些数据应该删除。但是在一些极端的情况下,例如服务器返回的数据没有设置Cache废弃的时间,或者是本地的Cache文件系统与返回的缓存数据有冲突,或者是某些特殊的网络环境导致HttpResponseCache工作异常,在这些情况下就需要我们自己来实现Http的缓存Cache。 实现自定义的http缓存,需要解决两个问题:第一个是实现一个DiskCacheManager,另外一个是制定Cache的缓存策略。关于DiskCacheManager,我们可以扩展Android系统提供的DiskLruCache来实现。而Cache的缓存策略,相对来说复杂一些,我们可能需要把部分JSON数据设计成不能缓存的,另外一些JSON数据设计成可以缓存几天的,把缩略图设计成缓存一两天的等等,为不同的数据类型根据他们的使用特点制定不同的缓存策略。 想要比较好的实现这两件事情,如果全部自己从头开始写会比较繁琐复杂,所幸的是,有不少著名的开源框架帮助我们快速的解决了那些问题。我们可以使用Volly,okHTTP,Picasso来实现网络缓存。 实现好网络缓存之后,我们可以使用Android Studio里面的Network Traffic Tools来查看网络数据的请求与返回情况,另外我们还可以使用AT&T ARO工具来抓取网络数据包进行分析查看。 2)Optimizing Network Request Frequencies 应用程序的一个基础功能是能够保持确保界面上呈现的信息是即时最新的,例如呈现最新的新闻,天气,信息流等等信息。但是,过于频繁的促使手机客户端应用去同步最新的服务器数据会对性能产生很大的负面影响,不仅仅使得CPU不停的在工作,内存,网络流量,电量等等都会持续的被消耗,所以在进行网络请求操作的时候一定要避免多度同步操作。 退到后台的应用为了能够在切换回前台的时候呈现最新的数据,会偷偷在后台不停的做同步的操作。这种行为会带来很严重的问题,首先因为网络请求的行为异常的耗电,其次不停的进行网络同步会耗费很多带宽流量。 为了能够尽量的减少不必要的同步操作,我们需要遵守下面的一些规则: 首先我们要对网络行为进行分类,区分需要立即更新数据的行为和其他可以进行延迟的更新行为,为不同的场景进行差异化处理。 其次要避免客户端对服务器的轮询操作,这样会浪费很多的电量与带宽流量。解决这个问题,我们可以使用Google Cloud Message来对更新的数据进行推送。 然后在某些必须做同步的场景下,需要避免使用固定的间隔频率来进行更新操作,我们应该在返回的数据无更新的时候,使用双倍的间隔时间来进行下一次同步。 最后更进一步,我们还可以通过判断当前设备的状态来决定同步的频率,例如判断设备处于休眠,运动等不同的状态设计各自不同时间间隔的同步频率。 另外,我们还可以通过判断设备是否连接上WiFi,是否正在充电来决定更新的频率。为了能够方便的实现这个功能,Android为我们提供了GCMNetworkManager来判断设备当下的状态,从而设计更加高效的网络同步操作,如下图所示: 3)Effective Prefetching 关于提升网络操作的性能,除了避免频繁的网络同步操作之外,还可以使用捆绑批量访问的方式来减少访问的频率,为了达到这个目的,我们就需要了解Prefetching。 举个例子,在某个场景下,一开始发出了网络请求得到了某张图片,隔了10s之后,发出第二次请求想要拿到另外一张图片,再隔了6s发出第三张图片的网络请求。这会导致设备的无线蜂窝一直处于高消耗的状态。Prefetching就是预先判定那些可能马上就会使用到的网络资源,捆绑一起集中进行网络请求。这样能够极大的减少电量的消耗,提升设备的续航时间。 使用Prefetching的难点在于如何判断事先获取的数据量到底是多少,如果预取的数据量偏少,那么就起不到什么效果,但是如果预取过多,又可能导致访问的时间过长。 那么问题来了,到底预取多少才比较合适呢?一个比较普适的规则是,在3G网络下可以预取1-5Mb的数据量,或者是按照提前预期后续1-2分钟的数据作为基线标准。在实际的操作当中,我们还需要考虑当前的网络速度来决定预取的数据量,例如在同样的时间下,4G网络可以获取到12张图片的数据,而2G网络则只能拿到3张图片的数据。所以,我们还需要把当前的网络环境情况添加到设计预取数据量的策略当中去。判断当前设备的状态与网络情况,可以使用前面提到过的GCMNetworkManager。 4)Adapting to Latency 网络延迟通常来说很容易被用户察觉到,严重的网络延迟会对用户体验造成很大的影响,用户很容易抱怨应用程序写的不好。 一个典型的网络操作行为,通常包含以下几个步骤:首先手机端发起网络请求,到达网络服务运营商的基站,再转移到服务提供者的服务器上,经过解码之后,接着访问本地的存储数据库,获取到数据之后,进行编码,最后按照原来传递的路径逐层返回。如下图所示: 在上面的网络请求链路当中的任何一个环节都有可能导致严重的延迟,成为性能瓶颈,但是这些环节可能出现的问题,客户端应用是无法进行调节控制的,应用能够做的就只是根据当前的网络环境选择当下最佳的策略来降低出现网络延迟的概率。主要的实施步骤有两步:第1步检测收集当前的网络环境信息,第2步根据当前收集到的信息进行网络请求行为的调整。 关于第1步检测当前的网络环境,我们可以使用系统提供的API来获取到相关的信息,如下图所示: 通过上面的示例,我们可以获取到移动网络的详细子类型,例如4G(LTE),3G等等,详细分类见下图,获取到详细的移动网络类型之后,我们可以根据当前网络的速率来调整网络请求的行为: 关于第2步根据收集到的信息进行策略的调整,通常来说,我们可以把网络请求延迟划分为三档:例如把网络延迟小于60ms的划分为GOOD,大于220ms的划分为BAD,介于两者之间的划分为OK(这里的60ms,220ms会需要根据不同的场景提前进行预算推测)。如果网络延迟属于GOOD的范畴,我们就可以做更多比较激进的预取数据的操作,如果网络延迟属于BAD的范畴,我们就应该考虑把当下的网络请求操作Hold住等待网络状况恢复到GOOD的状态再进行处理。 前面提到说60ms,220ms是需要提前自己预测的,可是预测的工作相当复杂。首先针对不同的机器与网络环境,网络延迟的三档阈值都不太一样,出现的概率也不尽相同,我们会需要针对这些不同的用户与设备选择不同的阈值进行差异化处理: Android官方为了帮助我们设计自己的网络请求策略,为我们提供了模拟器的网络流量控制功能来对实际环境进行模拟测量,或者还可以使用AT&T提供的AT&T Network Attenuator来帮助预估网络延迟。 5)Minimizing Asset Payload 为了能够减小网络传输的数据量,我们需要对传输的数据做压缩的处理,这样能够提高网络操作的性能。首先不同的网络环境,下载速度以及网络延迟是存在差异的,如下图所示: ...

2016年1月20日 · 1 分钟 · 天边的星星

Android获取手机底部虚拟按键高度

获取手机底部虚拟键盘的高度 魅族手机底部SmartBar高度 import android.content.Context; import android.content.res.Resources; import android.graphics.Point; import android.os.Build; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.view.ViewConfiguration; import android.view.WindowManager; import java.lang.reflect.Field; import java.lang.reflect.Method; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); Log.e(MainActivity.class.getName(), "hasNavBar1 = " + hasNavBar(MainActivity.this)); } }); Log.e(MainActivity.class.getName(),"ScreenHeight = "+getScreenHight()); Log.e(MainActivity.class.getName(),"SmartBarHeight = "+getSmartBarHeight(this)); Log.e(MainActivity.class.getName(),"hasNavBar = "+hasNavBar(this)); Log.e(MainActivity.class.getName(),"getNavigationBarHeight = "+getNavigationBarHeight(this)); } private int getScreenHight(){ // 获取屏幕高 Point point = new Point(); getWindowManager().getDefaultDisplay().getSize(point); int screenHeight = point.y + (isMeizu() ? 0 : getNavigationBarHeight(this)); return screenHeight; } /** * 获取虚拟按键栏高度 * @param context * @return */ public static int getNavigationBarHeight(Context context) { int result = 0; if (hasNavBar(context)){ Resources res = context.getResources(); int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId &gt; 0) { result = res.getDimensionPixelSize(resourceId); } } return result; } /** * 检查是否存在虚拟按键栏 * @param context * @return */ private static boolean hasNavBar(Context context) { Resources res = context.getResources(); int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android"); if (resourceId != 0) { boolean hasNav = res.getBoolean(resourceId); // check override flag String sNavBarOverride = getNavBarOverride(); if ("1".equals(sNavBarOverride)) { hasNav = false; } else if ("0".equals(sNavBarOverride)) { hasNav = true; } return hasNav; } else { // fallback return !ViewConfiguration.get(context).hasPermanentMenuKey(); } } /** * 判断虚拟按键栏是否重写 * @return */ private static String getNavBarOverride() { String sNavBarOverride = null; if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.KITKAT) { try { Class c = Class.forName("android.os.SystemProperties"); Method m = c.getDeclaredMethod("get", String.class); m.setAccessible(true); sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); } catch (Throwable e) { } } return sNavBarOverride; } /** * 判断是否meizu手机 * @return */ public static boolean isMeizu() { return Build.BRAND.equals("Meizu"); } /** * 获取魅族手机底部虚拟键盘高度 * @param context * @return */ public static int getSmartBarHeight(Context context) { try { Class c = Class.forName("com.android.internal.R$dimen"); Object obj = c.newInstance(); Field field = c.getField("mz_action_button_min_height"); int height = Integer.parseInt(field.get(obj).toString()); return context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return 0; } } import java.lang.reflect.Field; <td id="file-smartbarutils-java-LC4" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">java.lang.reflect.InvocationTargetException</span>; </td> <td id="file-smartbarutils-java-LC5" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">java.lang.reflect.Method</span>; </td> <td id="file-smartbarutils-java-LC6" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC7" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.app.ActionBar</span>; </td> <td id="file-smartbarutils-java-LC8" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.content.Context</span>; </td> <td id="file-smartbarutils-java-LC9" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.content.res.Configuration</span>; </td> <td id="file-smartbarutils-java-LC10" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.os.Build</span>; </td> <td id="file-smartbarutils-java-LC11" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.support.v4.app.FragmentActivity</span>; </td> <td id="file-smartbarutils-java-LC12" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.view.View</span>; </td> <td id="file-smartbarutils-java-LC13" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.view.Window</span>; </td> <td id="file-smartbarutils-java-LC14" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">import</span> <span class="pl-smi">android.view.WindowManager</span>; </td> <td id="file-smartbarutils-java-LC15" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC16" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-en">SmartBarUtils</span> { </td> <td id="file-smartbarutils-java-LC17" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC18" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">final</span> <span class="pl-k">int</span> <span class="pl-c1">SMART_BAR_HEIGH</span> <span class="pl-k">=</span> <span class="pl-c1">96</span>; </td> <td id="file-smartbarutils-java-LC19" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC20" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC21" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 调用 ActionBar.setTabsShowAtBottom(boolean) 方法。 如果</span> </td> <td id="file-smartbarutils-java-LC22" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * android:uiOptions=&#8221;splitActionBarWhenNarrow&#8221;,则可设置ActionBar Tabs显示在底栏。</span> </td> <td id="file-smartbarutils-java-LC23" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC24" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 示例: public class MyActivity extends Activity implements</span> </td> <td id="file-smartbarutils-java-LC25" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * ActionBar.TabListener { protected void onCreate(Bundle</span> </td> <td id="file-smartbarutils-java-LC26" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * savedInstanceState) { super.onCreate(savedInstanceState); &#8230;</span> </td> <td id="file-smartbarutils-java-LC27" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC28" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * final ActionBar bar = getActionBar();</span> </td> <td id="file-smartbarutils-java-LC29" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);</span> </td> <td id="file-smartbarutils-java-LC30" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * SmartBarUtils.setActionBarTabsShowAtBottom(bar, true);</span> </td> <td id="file-smartbarutils-java-LC31" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC32" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * bar.addTab(bar.newTab().setText(&quot;tab1&quot;).setTabListener(this));</span> </td> <td id="file-smartbarutils-java-LC33" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * &#8230; } }</span> </td> <td id="file-smartbarutils-java-LC34" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC35" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC36" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">setActionBarTabsShowAtBottom</span>(<span class="pl-smi">ActionBar</span> <span class="pl-v">actionbar</span>, </td> <td id="file-smartbarutils-java-LC37" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">boolean</span> <span class="pl-v">showAtBottom</span>) { </td> <td id="file-smartbarutils-java-LC38" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC39" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> method <span class="pl-k">=</span> <span class="pl-smi">Class</span><span class="pl-k">.</span>forName(<span class="pl-s"><span class="pl-pds">&#8220;</span>android.app.ActionBar<span class="pl-pds">&#8220;</span></span>)<span class="pl-k">.</span>getMethod( </td> <td id="file-smartbarutils-java-LC40" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>setTabsShowAtBottom<span class="pl-pds">&#8220;</span></span>, <span class="pl-k">new</span> <span class="pl-smi">Class</span>[] { <span class="pl-k">boolean</span><span class="pl-k">.</span>class }); </td> <td id="file-smartbarutils-java-LC41" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC42" class="blob-code blob-code-inner js-file-line"> method<span class="pl-k">.</span>invoke(actionbar, showAtBottom); </td> <td id="file-smartbarutils-java-LC43" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalArgumentException</span> e) { </td> <td id="file-smartbarutils-java-LC44" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC45" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalAccessException</span> e) { </td> <td id="file-smartbarutils-java-LC46" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC47" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">InvocationTargetException</span> e) { </td> <td id="file-smartbarutils-java-LC48" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC49" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC50" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">SecurityException</span> e) { </td> <td id="file-smartbarutils-java-LC51" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC52" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">NoSuchMethodException</span> e) { </td> <td id="file-smartbarutils-java-LC53" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC54" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">ClassNotFoundException</span> e) { </td> <td id="file-smartbarutils-java-LC55" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC56" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC57" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC58" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC59" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC60" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 调用 ActionBar.setActionBarViewCollapsable(boolean) 方法。</span> </td> <td id="file-smartbarutils-java-LC61" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 设置ActionBar顶栏无显示内容时是否隐藏。</span> </td> <td id="file-smartbarutils-java-LC62" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC63" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 示例:</span> </td> <td id="file-smartbarutils-java-LC64" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC65" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * public class MyActivity extends Activity {</span> </td> <td id="file-smartbarutils-java-LC66" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC67" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * protected void onCreate(Bundle savedInstanceState) {</span> </td> <td id="file-smartbarutils-java-LC68" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * super.onCreate(savedInstanceState); &#8230;</span> </td> <td id="file-smartbarutils-java-LC69" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC70" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * final ActionBar bar = getActionBar();</span> </td> <td id="file-smartbarutils-java-LC71" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC72" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * // 调用setActionBarViewCollapsable,并设置ActionBar没有显示内容,则ActionBar顶栏不显示</span> </td> <td id="file-smartbarutils-java-LC73" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * SmartBarUtils.setActionBarViewCollapsable(bar, true);</span> </td> <td id="file-smartbarutils-java-LC74" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * bar.setDisplayOptions(0); } }</span> </td> <td id="file-smartbarutils-java-LC75" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC76" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">setActionBarViewCollapsable</span>(<span class="pl-smi">ActionBar</span> <span class="pl-v">actionbar</span>, </td> <td id="file-smartbarutils-java-LC77" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">boolean</span> <span class="pl-v">collapsable</span>) { </td> <td id="file-smartbarutils-java-LC78" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC79" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> method <span class="pl-k">=</span> <span class="pl-smi">Class</span><span class="pl-k">.</span>forName(<span class="pl-s"><span class="pl-pds">&#8220;</span>android.app.ActionBar<span class="pl-pds">&#8220;</span></span>)<span class="pl-k">.</span>getMethod( </td> <td id="file-smartbarutils-java-LC80" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>setActionBarViewCollapsable<span class="pl-pds">&#8220;</span></span>, </td> <td id="file-smartbarutils-java-LC81" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">new</span> <span class="pl-smi">Class</span>[] { <span class="pl-k">boolean</span><span class="pl-k">.</span>class }); </td> <td id="file-smartbarutils-java-LC82" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC83" class="blob-code blob-code-inner js-file-line"> method<span class="pl-k">.</span>invoke(actionbar, collapsable); </td> <td id="file-smartbarutils-java-LC84" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalArgumentException</span> e) { </td> <td id="file-smartbarutils-java-LC85" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC86" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalAccessException</span> e) { </td> <td id="file-smartbarutils-java-LC87" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC88" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">InvocationTargetException</span> e) { </td> <td id="file-smartbarutils-java-LC89" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC90" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC91" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">SecurityException</span> e) { </td> <td id="file-smartbarutils-java-LC92" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC93" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">NoSuchMethodException</span> e) { </td> <td id="file-smartbarutils-java-LC94" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC95" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">ClassNotFoundException</span> e) { </td> <td id="file-smartbarutils-java-LC96" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC97" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC98" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC99" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC100" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC101" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 调用 ActionBar.setActionModeHeaderHidden(boolean) 方法。 设置ActionMode顶栏是否隐藏。</span> </td> <td id="file-smartbarutils-java-LC102" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC103" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * public class MyActivity extends Activity {</span> </td> <td id="file-smartbarutils-java-LC104" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC105" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * protected void onCreate(Bundle savedInstanceState) {</span> </td> <td id="file-smartbarutils-java-LC106" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * super.onCreate(savedInstanceState); &#8230;</span> </td> <td id="file-smartbarutils-java-LC107" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC108" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * final ActionBar bar = getActionBar();</span> </td> <td id="file-smartbarutils-java-LC109" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC110" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * // ActionBar转为ActionMode时,不显示ActionMode顶栏</span> </td> <td id="file-smartbarutils-java-LC111" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * SmartBarUtils.setActionModeHeaderHidden(bar, true); } }</span> </td> <td id="file-smartbarutils-java-LC112" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC113" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">setActionModeHeaderHidden</span>(<span class="pl-smi">ActionBar</span> <span class="pl-v">actionbar</span>, </td> <td id="file-smartbarutils-java-LC114" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">boolean</span> <span class="pl-v">hidden</span>) { </td> <td id="file-smartbarutils-java-LC115" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC116" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> method <span class="pl-k">=</span> <span class="pl-smi">Class</span><span class="pl-k">.</span>forName(<span class="pl-s"><span class="pl-pds">&#8220;</span>android.app.ActionBar<span class="pl-pds">&#8220;</span></span>)<span class="pl-k">.</span>getMethod( </td> <td id="file-smartbarutils-java-LC117" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>setActionModeHeaderHidden<span class="pl-pds">&#8220;</span></span>, <span class="pl-k">new</span> <span class="pl-smi">Class</span>[] { <span class="pl-k">boolean</span><span class="pl-k">.</span>class }); </td> <td id="file-smartbarutils-java-LC118" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC119" class="blob-code blob-code-inner js-file-line"> method<span class="pl-k">.</span>invoke(actionbar, hidden); </td> <td id="file-smartbarutils-java-LC120" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalArgumentException</span> e) { </td> <td id="file-smartbarutils-java-LC121" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC122" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalAccessException</span> e) { </td> <td id="file-smartbarutils-java-LC123" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC124" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">InvocationTargetException</span> e) { </td> <td id="file-smartbarutils-java-LC125" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC126" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC127" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">SecurityException</span> e) { </td> <td id="file-smartbarutils-java-LC128" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC129" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">NoSuchMethodException</span> e) { </td> <td id="file-smartbarutils-java-LC130" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC131" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">ClassNotFoundException</span> e) { </td> <td id="file-smartbarutils-java-LC132" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC133" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC134" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC135" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC136" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC137" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 原隐藏SmartBar的方法</span> </td> <td id="file-smartbarutils-java-LC138" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 此方法已从Flyme2.4.1开始失效 示例:</span> </td> <td id="file-smartbarutils-java-LC139" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC140" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * final ActionBar actionBar = getActionBar(); SmartBarUtils.hide(this);</span> </td> <td id="file-smartbarutils-java-LC141" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC142" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC143" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">@Deprecated</span> </td> <td id="file-smartbarutils-java-LC144" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">final</span> <span class="pl-k">void</span> <span class="pl-en">hide</span>(<span class="pl-smi">FragmentActivity</span> <span class="pl-v">activity</span>) { </td> <td id="file-smartbarutils-java-LC145" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">ActionBar</span> actionBar <span class="pl-k">=</span> activity<span class="pl-k">.</span>getActionBar(); </td> <td id="file-smartbarutils-java-LC146" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (actionBar <span class="pl-k">==</span> <span class="pl-c1">null</span>) { </td> <td id="file-smartbarutils-java-LC147" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span>; </td> <td id="file-smartbarutils-java-LC148" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC149" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Class<? extends <span class="pl-smi">ActionBar</span>></span> <span class="pl-smi">ActionBarClass</span> <span class="pl-k">=</span> actionBar<span class="pl-k">.</span>getClass(); </td> <td id="file-smartbarutils-java-LC150" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> setTabsShowAtBottom; </td> <td id="file-smartbarutils-java-LC151" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC152" class="blob-code blob-code-inner js-file-line"> setTabsShowAtBottom <span class="pl-k">=</span> <span class="pl-smi">ActionBarClass</span><span class="pl-k">.</span>getMethod( </td> <td id="file-smartbarutils-java-LC153" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>setTabsShowAtBottom<span class="pl-pds">&#8220;</span></span>, <span class="pl-smi">Boolean</span><span class="pl-c1"><span class="pl-k">.</span>TYPE</span>); </td> <td id="file-smartbarutils-java-LC154" class="blob-code blob-code-inner js-file-line"> setTabsShowAtBottom<span class="pl-k">.</span>invoke(activity<span class="pl-k">.</span>getActionBar(), <span class="pl-c1">true</span>); </td> <td id="file-smartbarutils-java-LC155" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">NoSuchMethodException</span> e) { </td> <td id="file-smartbarutils-java-LC156" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC157" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalArgumentException</span> e) { </td> <td id="file-smartbarutils-java-LC158" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC159" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">IllegalAccessException</span> e) { </td> <td id="file-smartbarutils-java-LC160" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC161" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">InvocationTargetException</span> e) { </td> <td id="file-smartbarutils-java-LC162" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC163" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC164" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC165" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC166" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC167" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 以下三个方法原作者为c跳跳(http://weibo.com/u/1698085875),</span> </td> <td id="file-smartbarutils-java-LC168" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 由Shawn(http://weibo.com/linshen2011)在其基础上改进了一种判断SmartBar是否存在的方法,</span> </td> <td id="file-smartbarutils-java-LC169" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 注意该方法反射的接口只存在于2013年6月之后魅族的flyme固件中</span> </td> <td id="file-smartbarutils-java-LC170" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC171" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC172" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC173" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 方法一:uc等在使用的方法(新旧版flyme均有效),</span> </td> <td id="file-smartbarutils-java-LC174" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 此方法需要配合requestWindowFeature(Window.FEATURE_NO_TITLE</span> </td> <td id="file-smartbarutils-java-LC175" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * )使用,缺点是程序无法使用系统actionbar</span> </td> <td id="file-smartbarutils-java-LC176" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC177" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param decorView</span> </td> <td id="file-smartbarutils-java-LC178" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * window.getDecorView</span> </td> <td id="file-smartbarutils-java-LC179" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC180" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">hide</span>(<span class="pl-smi">View</span> <span class="pl-v">decorView</span>) { </td> <td id="file-smartbarutils-java-LC181" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (<span class="pl-k">!</span>hasSmartBar()) </td> <td id="file-smartbarutils-java-LC182" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span>; </td> <td id="file-smartbarutils-java-LC183" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC184" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC185" class="blob-code blob-code-inner js-file-line"> @SuppressWarnings(<span class="pl-s"><span class="pl-pds">&#8220;</span>rawtypes<span class="pl-pds">&#8220;</span></span>) </td> <td id="file-smartbarutils-java-LC186" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Class</span>[] arrayOfClass <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">Class</span>[<span class="pl-c1">1</span>]; </td> <td id="file-smartbarutils-java-LC187" class="blob-code blob-code-inner js-file-line"> arrayOfClass[<span class="pl-c1"></span>] <span class="pl-k">=</span> <span class="pl-smi">Integer</span><span class="pl-c1"><span class="pl-k">.</span>TYPE</span>; </td> <td id="file-smartbarutils-java-LC188" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> localMethod <span class="pl-k">=</span> <span class="pl-smi">View</span><span class="pl-k">.</span>class<span class="pl-k">.</span>getMethod(<span class="pl-s"><span class="pl-pds">&#8220;</span>setSystemUiVisibility<span class="pl-pds">&#8220;</span></span>, </td> <td id="file-smartbarutils-java-LC189" class="blob-code blob-code-inner js-file-line"> arrayOfClass); </td> <td id="file-smartbarutils-java-LC190" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Field</span> localField <span class="pl-k">=</span> <span class="pl-smi">View</span><span class="pl-k">.</span>class </td> <td id="file-smartbarutils-java-LC191" class="blob-code blob-code-inner js-file-line"> .getField(<span class="pl-s"><span class="pl-pds">&#8220;</span>SYSTEM_UI_FLAG_HIDE_NAVIGATION<span class="pl-pds">&#8220;</span></span>); </td> <td id="file-smartbarutils-java-LC192" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Object</span>[] arrayOfObject <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">Object</span>[<span class="pl-c1">1</span>]; </td> <td id="file-smartbarutils-java-LC193" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC194" class="blob-code blob-code-inner js-file-line"> arrayOfObject[<span class="pl-c1"></span>] <span class="pl-k">=</span> localField<span class="pl-k">.</span>get(<span class="pl-c1">null</span>); </td> <td id="file-smartbarutils-java-LC195" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> e) { </td> <td id="file-smartbarutils-java-LC196" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC197" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC198" class="blob-code blob-code-inner js-file-line"> localMethod<span class="pl-k">.</span>invoke(decorView, arrayOfObject); </td> <td id="file-smartbarutils-java-LC199" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span>; </td> <td id="file-smartbarutils-java-LC200" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> e) { </td> <td id="file-smartbarutils-java-LC201" class="blob-code blob-code-inner js-file-line"> e<span class="pl-k">.</span>printStackTrace(); </td> <td id="file-smartbarutils-java-LC202" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC203" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC204" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC205" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC206" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 方法二:此方法需要配合requestWindowFeature(Window.FEATURE_NO_TITLE)使用</span> </td> <td id="file-smartbarutils-java-LC207" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * ,缺点是程序无法使用系统actionbar</span> </td> <td id="file-smartbarutils-java-LC208" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC209" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param context</span> </td> <td id="file-smartbarutils-java-LC210" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param window</span> </td> <td id="file-smartbarutils-java-LC211" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC212" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">hide</span>(<span class="pl-smi">Context</span> <span class="pl-v">context</span>, <span class="pl-smi">Window</span> <span class="pl-v">window</span>) { </td> <td id="file-smartbarutils-java-LC213" class="blob-code blob-code-inner js-file-line"> hide(context, window, <span class="pl-c1"></span>); </td> <td id="file-smartbarutils-java-LC214" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC215" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC216" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">getStatusBarHeight</span>(<span class="pl-smi">Context</span> <span class="pl-v">context</span>) { </td> <td id="file-smartbarutils-java-LC217" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">int</span> result <span class="pl-k">=</span> <span class="pl-c1"></span>; </td> <td id="file-smartbarutils-java-LC218" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">int</span> resourceId <span class="pl-k">=</span> context<span class="pl-k">.</span>getResources()<span class="pl-k">.</span>getIdentifier( </td> <td id="file-smartbarutils-java-LC219" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>status_bar_height<span class="pl-pds">&#8220;</span></span>, <span class="pl-s"><span class="pl-pds">&#8220;</span>dimen<span class="pl-pds">&#8220;</span></span>, <span class="pl-s"><span class="pl-pds">&#8220;</span>android<span class="pl-pds">&#8220;</span></span>); </td> <td id="file-smartbarutils-java-LC220" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (resourceId <span class="pl-k">></span> <span class="pl-c1"></span>) { </td> <td id="file-smartbarutils-java-LC221" class="blob-code blob-code-inner js-file-line"> result <span class="pl-k">=</span> context<span class="pl-k">.</span>getResources()<span class="pl-k">.</span>getDimensionPixelSize(resourceId); </td> <td id="file-smartbarutils-java-LC222" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC223" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> result; </td> <td id="file-smartbarutils-java-LC224" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC225" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC226" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC227" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 方法三:需要使用顶部actionbar的应用请使用此方法</span> </td> <td id="file-smartbarutils-java-LC228" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * </span> </td> <td id="file-smartbarutils-java-LC229" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param context</span> </td> <td id="file-smartbarutils-java-LC230" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param window</span> </td> <td id="file-smartbarutils-java-LC231" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @param smartBarHeight</span> </td> <td id="file-smartbarutils-java-LC232" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * set SmartBarUtils.SMART_BAR_HEIGHT_PIXEL</span> </td> <td id="file-smartbarutils-java-LC233" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC234" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">hide</span>(<span class="pl-smi">Context</span> <span class="pl-v">context</span>, <span class="pl-smi">Window</span> <span class="pl-v">window</span>, <span class="pl-k">int</span> <span class="pl-v">smartBarHeight</span>) { </td> <td id="file-smartbarutils-java-LC235" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (<span class="pl-k">!</span>hasSmartBar()) { </td> <td id="file-smartbarutils-java-LC236" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span>; </td> <td id="file-smartbarutils-java-LC237" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC238" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (context<span class="pl-k">.</span>getResources()<span class="pl-k">.</span>getConfiguration()<span class="pl-k">.</span>orientation <span class="pl-k">==</span> <span class="pl-smi">Configuration</span><span class="pl-c1"><span class="pl-k">.</span>ORIENTATION_LANDSCAPE</span>) { </td> <td id="file-smartbarutils-java-LC239" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span>; </td> <td id="file-smartbarutils-java-LC240" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC241" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC242" class="blob-code blob-code-inner js-file-line"> window<span class="pl-k">.</span>setFlags(<span class="pl-smi">WindowManager</span><span class="pl-k">.</span><span class="pl-smi">LayoutParams</span><span class="pl-c1"><span class="pl-k">.</span>FLAG_FULLSCREEN</span>, </td> <td id="file-smartbarutils-java-LC243" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">WindowManager</span><span class="pl-k">.</span><span class="pl-smi">LayoutParams</span><span class="pl-c1"><span class="pl-k">.</span>FLAG_FULLSCREEN</span>); </td> <td id="file-smartbarutils-java-LC244" class="blob-code blob-code-inner js-file-line"> window<span class="pl-k">.</span>addFlags(<span class="pl-smi">WindowManager</span><span class="pl-k">.</span><span class="pl-smi">LayoutParams</span><span class="pl-c1"><span class="pl-k">.</span>FLAG_FORCE_NOT_FULLSCREEN</span>); </td> <td id="file-smartbarutils-java-LC245" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">int</span> statusBarHeight <span class="pl-k">=</span> getStatusBarHeight(context); </td> <td id="file-smartbarutils-java-LC246" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC247" class="blob-code blob-code-inner js-file-line"> window<span class="pl-k">.</span>getDecorView() </td> <td id="file-smartbarutils-java-LC248" class="blob-code blob-code-inner js-file-line"> .setPadding(<span class="pl-c1"></span>, statusBarHeight, <span class="pl-c1"></span>, <span class="pl-k">&#8211;</span>smartBarHeight); </td> <td id="file-smartbarutils-java-LC249" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC250" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC251" class="blob-code blob-code-inner js-file-line"> <span class="pl-c">/**</span> </td> <td id="file-smartbarutils-java-LC252" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * 新型号可用反射调用Build.hasSmartBar()来判断有无SmartBar</span> </td> <td id="file-smartbarutils-java-LC253" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> * @return</span> </td> <td id="file-smartbarutils-java-LC254" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"> */</span> </td> <td id="file-smartbarutils-java-LC255" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">hasSmartBar</span>() { </td> <td id="file-smartbarutils-java-LC256" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> { </td> <td id="file-smartbarutils-java-LC257" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Method</span> method <span class="pl-k">=</span> <span class="pl-smi">Class</span><span class="pl-k">.</span>forName(<span class="pl-s"><span class="pl-pds">&#8220;</span>android.os.Build<span class="pl-pds">&#8220;</span></span>)<span class="pl-k">.</span>getMethod( </td> <td id="file-smartbarutils-java-LC258" class="blob-code blob-code-inner js-file-line"> <span class="pl-s"><span class="pl-pds">&#8220;</span>hasSmartBar<span class="pl-pds">&#8220;</span></span>); </td> <td id="file-smartbarutils-java-LC259" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> ((<span class="pl-smi">Boolean</span>) method<span class="pl-k">.</span>invoke(<span class="pl-c1">null</span>))<span class="pl-k">.</span>booleanValue(); </td> <td id="file-smartbarutils-java-LC260" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> e) { </td> <td id="file-smartbarutils-java-LC261" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC262" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC263" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (<span class="pl-smi">Build</span><span class="pl-c1"><span class="pl-k">.</span>DEVICE</span><span class="pl-k">.</span>equals(<span class="pl-s"><span class="pl-pds">&#8220;</span>mx2<span class="pl-pds">&#8220;</span></span>)) { </td> <td id="file-smartbarutils-java-LC264" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">true</span>; </td> <td id="file-smartbarutils-java-LC265" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">else</span> <span class="pl-k">if</span> (<span class="pl-smi">Build</span><span class="pl-c1"><span class="pl-k">.</span>DEVICE</span><span class="pl-k">.</span>equals(<span class="pl-s"><span class="pl-pds">&#8220;</span>mx<span class="pl-pds">&#8220;</span></span>) <span class="pl-k">||</span> <span class="pl-smi">Build</span><span class="pl-c1"><span class="pl-k">.</span>DEVICE</span><span class="pl-k">.</span>equals(<span class="pl-s"><span class="pl-pds">&#8220;</span>m9<span class="pl-pds">&#8220;</span></span>)) { </td> <td id="file-smartbarutils-java-LC266" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>; </td> <td id="file-smartbarutils-java-LC267" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC268" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>; </td> <td id="file-smartbarutils-java-LC269" class="blob-code blob-code-inner js-file-line"> } </td> <td id="file-smartbarutils-java-LC270" class="blob-code blob-code-inner js-file-line"> </td> <td id="file-smartbarutils-java-LC271" class="blob-code blob-code-inner js-file-line"> } </td>

2016年1月15日 · 16 分钟 · 天边的星星

在低版本android系统上实现Material design应用

Material Design真的很好看,动画效果真的很实用。前面也写了一些文章介绍如何编写Material风格的程序,但是很多都是一些新的api,低版本上面没有这些api,我们没办法使用。但是不用气馁,google官方,以及一些大牛,给我们提供了一些程序,让我们在低版本上面可以实现Material风格的程序,这里就给大家介绍一下。 妹子图截屏 使用support library 使用support library最新的版本,appcomt21,可以在较低版本上面实现部分风格,在之前的文章我已经说过了,这里在系统的说一下。 应用主题 这部分的话之前的文章说过,链接在这里: http://blog.isming.me/2014/10/18/creating-android-app-with-material-design-one-theme/ 使用gralde进行构建的话,在依赖中添加v7包: [?](http://www.open-open.com/lib/view/open1416277425289.html#) <table border="0" cellspacing="0" cellpadding="0"> <tr> <td class="gutter"> <div class="line number1 index0 alt2"> 1 </div> <div class="line number2 index1 alt1"> 2 </div> <div class="line number3 index2 alt2"> 3 </div> <div class="line number4 index3 alt1"> 4 </div> <div class="line number5 index4 alt2"> 5 </div> </td> <td class="code"> <div class="container"> <div class="line number1 index0 alt2"> `dependencies {` </div> <div class="line number2 index1 alt1"> `compile ``'com.android.support:appcompat-v7:21.0.+'` </div> <div class="line number3 index2 alt2"> `compile ``'com.android.support:cardview-v7:21.0.+'` </div> <div class="line number4 index3 alt1"> `compile ``'com.android.support:recyclerview-v7:21.0.+'` </div> <div class="line number5 index4 alt2"> `}` </div> </div> </td> </tr> </table> 使用eclipse构建的话,加入最新的appcompat包即可。 ...

2016年1月5日 · 5 分钟 · 天边的星星