参考
例如EditText右侧有一个删除按钮是通过drawableRight属性设置的,此时如果想让其响应点击事件,这可以通过判断点击的坐标位置与删除按钮的位置对比,下面是通过处理点击删除按钮删除EditText框的内容
重写RecyclerView.Adapter的2个方法
重写RecycleView的setLayoutManager方法
前提是得确定头部和尾部的位置,即isHeaderViewPosition和isFooterViewPosition的逻辑了.通过adapter就可以计算出是否是头部还是尾部的位置了.
重写AppCompatRadioButton的onDraw方法
重写AppCompatRadioButton的toggle方法
重写SwipeRefreshLayout的onStartNestedScroll方法
更新于2019-01-03
TextView设置的文本默认是存在一个上下间距的,也就是上下空白,当我们在使用drawableLeft的时候,这个默认的空白会使TextView中的文本向下偏移,当你的drawableLeft使用的icon很小,文字的size也很小的时候,即使你设置了android:gravity=“center”,也能很明显的看到你的TextView中的文本基本上是与icon处于底边对其,而不是居中对其
只要TextView中加上android:includeFontPadding=“false” 这个属性属性就可以了!
代码设置 :
setDuplicateParentStateEnabled(true)
布局设置:
android:duplicateParentState=“true”
更新于2019-01-08
使用方式
更新于2019-01-10
#更新于2019-01-17
重写RecycleView的onTouchEvent方法
如果还需要实现回滚完毕后跳去新页面,则可以监听其滚动,当滚动停止的时候就可以跳去新页面了.
例如:
#更新于2019-01-24
例如限制EditText最大只能输入150个字,超出后提示文案
使用方式如下:
更新于2019-01-26
前提是设备已经root过了.
更新于2019-01-30
更新于2019-02-28
1.文字颜色选择器
2.图片背景选择器
更新于2019-03-05
更新于2019-03-07
更新于2019-03-08
假设布局里面已经给View设置了一个shape作为背景图片了,如果我想在代码中修改它的圆角的话,可以通过这种方式修改:
更新于2019-03-13
两种方式:
1、禁用全局多点触控:
在application引用的Theme中添加以下代码:
2、如果要单独对某个界面禁用,则需要的在相应的xml或代码中添加:
或
注意:必须是需要禁止多点触控的控件的上层父类中添加! 父类的父类加了无效。 另外,该属性实在Android API level 11 之后才有的。
更新于2019-03-25
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
用过ScaleAnimation的人都知道,可以直接在构造方法中设置,但是如果是使用ObjectAnimator或者是直接setScaleX和setScaleY的方式那要怎么设置缩放中心点呢??
答案是使用View的setPivotX和setPivotY方法单独设置,源码如下:
例如设置右下角为缩放中心点可以这样弄target.setPivotX(target.getWidth());target.setPivotY(target.getHeight());
更新于2019-04-15
详情看这里
更新于2019-04-17
详情看这里
更新于2019-04-23
将启动图通过样式的方式设置
然后在启动Activity使用该样式
然后LaunchActivity就不需要做任何操作了,如果启动图还有广告图的话,那只需要在布局中添加广告图的布局,代码中书写广告的
加载逻辑就可以了,无需关心默认的启动图,因为广告图显示的时候会自动覆盖默认的的启动图.
例如:
更新于2019-04-23
查看详情
更新于2019-04-26
由于瀑布流布局,每个item的高度都是不定的,所以当滑动了很多页的时候,滚出屏幕的item已经回收掉了,而当再次滑动回到列表顶部的时候,由于item需要重新布局,所以会看到切换动画, 解决办法如下:
步骤一: 去掉切换动画
步骤二:解决顶部留白的问题
更新于2019/05/16
org.gradle.jvmargs=-Xmx1536m : 用来加快gradle的编译!
android.enableAapt2=false
Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception:
android.useDeprecatedNdk=true
Error:(12, 0) Error: NDK integration is deprecated in the current plugin.
Consider trying the new experimental plugin.
For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.
Set “android.useDeprecatedNdk=true” in gradle.properties to continue using the current NDK integration.
android.injected.testOnly=false
让debug包也可以下载安装.
更新于2019/06/4
方式1:把textview的字体大小设置为PX为单位,原因是px不随系统而改变。
方式2:在BaseActivity重写 getResources()方法,具体代码如下
更新于2019/06/12
方式一:
在style文件中添加自定义样式,并继承@android:style/Theme.Dialog
然后,自定义的Dialog的构造方法中使用该样式
方式二:
代码设置,在自定义的Dialog中加入这段代码
需要强调一点的是,导航栏是在App页面的最上面的,所以透明后,是可以看到dialog的背景的.
更新于2019/06/27
更新于2019/07/27
这个得从FragmentPagerAdapter的instantiateItem方法查看
定位到这一句,继续查找FragmentManager的实现类FragmentManagerImpl
中的findFragmentByTag方法
观察mAdded和mActive 变量,他们就是用来存储Fragment的容器
所以如果想要ViewPager重新初始化已加载的Fragment的话,就得通过反射清空这2个容器.
更新于2019/08/7
详情
在ViewPager的PagerAdapter里面有一个回调方法,源码如下:
我们只需要重写该方法,然后记录当前的View
之后再对外提供一个方法获取该View即可
使用方式:
getWindowVisibleDisplayFrame()是View类下的一个方法,用来获取当前窗口可视区域的大小。该方法原型为:
outRect中保存了可视区域的范围,如left, top, right, bottom。
该方法使用注意事项:
-
调用该方法的view对象必须在有效的window中,比如activity,fragment或者dialog的layout中。类似new TextView(context).getWindowVisibleDisplayFrame(rect)无法得到正确的结果。
-
该方法必须在view已经attach到window时调用才能得到期望的正确结果。比如我们可以在Activity、Fragment和Dialog的onWindowFocusChanged()方法中执行,在view的onAttachedToWindow()中可能无法获得正确结果
-
outRect所表示的只是窗体可见范围,其会受到系统状态栏,虚拟键盘和导航栏的影响,状态栏主要影响outRect的top值,虚拟键盘和导航栏会影响outRect的bottom值
详情
这个播放器支持surfaceView和TextureView 两种视图模式的展示,
对于surfaceView好像做不到转换成bitmap 但是TextureView 就很简单了.
方法一:
方法二:
参考
然后使用时在res/values/styles.xml中定义要解析的style即可
并且在res/values/attrs.xml中自定义属性名
如果直接将其它的aar包放到module的libs就开始打包,虽然也可以打成功,但是生成aar包放到项目中使用的时候如果访问该aar所依赖的其它aa的类就会报找不到目标类的异常,解决办法就是还得在项目中依赖这个aar所依赖的其他aar包,显然这并不是我们所期望的.
这里介绍正确的解决方案是使用fat-aar-android插件.
fat-aar可以解决aar嵌套aar打包的需求场景.
使用步骤如下:
1.编辑主工程的build.gradle文件
2.编辑需要打包生成aar的module工程的build.gradle文件
方法参数是 (float x, float y),作用是查找指定坐标点 (x, y) 落于 RecyclerView 的哪个子 View 上面,这里的坐标点是以 RecyclerView 控件作为坐标轴,并不是以屏幕左上角作为坐标原点。方法的源码如下:
这个ChildHelper类,它会协助获取RecyclerView中的childVIew,并提供忽略隐藏Children的功能,也就是说,调它的getChildAt只会在当前显示的Children中去查找,如果想查HiddenChildren,那么可以调getUnfilteredChildAt。
调用setLayoutFrozen()该方法传入true,其实等效于关闭了 ReyclerView 的刷新,不管数据源发生了何种变化,不管用户滑动了多长距离,都不会去刷新界面,看起来就像是不响应一样,但等到再次调用该方法参数传入 false 后,就会立马去根据变化后的数据源来刷新界面了。
使用场景还是有的,假如有些场景暂时不想让 RecyclerView 去刷新,比如此时有其他动画效果正在执行中,RecyclerView 刷新多少会有些耗时,万一导致了当前动画的卡顿,那么体验就不好了。所以,这个时候可以暂时将 ReyclerView 的刷新关闭掉,但后面记得要重新开启。
ps:新版本的RecyclerView该方法已标注为过时方法,可以使用suppressLayout代替.
该方法参数是 (View view),作用正如命名上的理解,查找含有指定 View 的 ItemView,而 ItemView 是指 RecyclerView 的直接子 View
通常,RecyclerView 的 Item 布局都不会简单到直接就是一个具体的 TextView,往往都挺复杂的。
本人华为荣耀20上试过有效,小米和vivo没试过,如果不行的话,可以试试如下方式:
只需要继承SimpleComponent和实现RefreshHeader接口即可,然后根据需求实现对应的文案或者动画效果
上面的效果就是下拉过程中文案会由"下拉刷新"->“释放立即刷新”->“释放立即刷新”->“刷新完成”, 而动画效果就是有一个加载圈在持续下拉的过程会根据下拉百分比来旋转,当变成"正在刷新…"的时候会播放旋转动画,当刷新完成后会取消动画
使用方式也很简单,全局使用可以在初始的时候配置如下:
IdleHandler是一个回调接口,可以通过MessageQueue的addIdleHandler添加实现类。当MessageQueue中的任务暂时处理完了(没有新任务或者下一个任务延时在之后),这个时候会回调这个接口,返回false,那么就会在回调之后移除它,返回true就会在下次message处理完了的时候继续回调。
registerForActivityResult()是startActivityForResult()的替代,简化了数据回调的写法
参考
1.安卓手机打开开发者模式连接上电脑
2.在谷歌浏览器中访问地址:
简单地说, 由于该语句使用 @aar notation, 所以 gradle 只会下载这一个 aar 文件, 而不会顺带着下载这个 aar 所需要的依赖文件. 所以需要 transitive 让依赖能够自动被下载. 一般而言, 去掉 @aar 以及 { transitive = true } 不会有任何问题.
这个字段的含义是: 是否自动更新该版本的依赖文件, 但是! 如果像本例中指定了版本, 则只会更新相同版本. 默认是 24 小时检查该依赖. 当然也可以指定检查更新的周期.
在执行build、compile等任务时会解析项目配置的依赖并按照配置的仓库去搜寻下载这些依赖。默认情况下,Gradle会依照Gradle缓存->你配置的仓库的顺序依次搜寻这些依赖,并且一旦找到就会停止搜索。如果想要忽略本地缓存每次都进行远程检索可以通过在执行命令时添加–refresh-dependencies参数来强制刷新依赖
当远程仓库上传了相同版本依赖时,有时需要为缓存指定一个时效去检查远程仓库的依赖笨版本,Gradle提供了
Gradle在按照配置的仓库去搜寻下载依赖时,下载的依赖默认会缓存到目录下,当然也可以手工修改这个位置。
Gradle还提供了一种离线模式,可以让你构建时总是采用缓存的内容而无需去联网检查,如果你并未采用动态版本特性且可以确保项目中依赖的版本都已经缓存到了本地,这无疑是提高构建速度的一个好选择。开启离线模式只需要在执行命令时候添加–offline参数即可。当然,采用这种模式的也是有代价的,如果缓存中搜寻不到所需依赖会导致构建失败。
在项目根gradle文件中修改如下,同时兼容gradle3.5.3和2.3.3插件版本
然后在app的gradle文件添加依赖的时候也要区分下,如下以tinker依赖添加为例
这2者的作用都是为了解决multiDex拆分包的过程中会出现在启动时需要用到的某个类没有在主dex中找到而产生java.lang.NoClassDefFoundError的崩溃问题.
1)使用multiDexKeepFile
您在 multiDexKeepFile 中指定的文件应该每行包含一个类,并且类采用 com/example/MyClass.class 格式。例如,您可以创建一个名为 multidex-config.txt 的文件,如下所示:
然后,您可以针对构建类型声明该文件,如下所示:
请注意,Gradle 会读取相对于 build.gradle 文件的路径,因此如果 multidex-config.txt 与 build.gradle 文件在同一目录中,以上示例将有效。
2)使用multiDexKeepProguard
multiDexKeepProguard 文件使用与 Proguard 相同的格式,并且支持全部 Proguard 语法。如需详细了解 Proguard 格式和语法,请参阅 Proguard 手册中的 Keep 选项一节。
您在 multiDexKeepProguard 中指定的文件应该在任何有效的 ProGuard 语法中包含 -keep 选项。例如 -keep com.example.MyClass.class。您可以创建一个名为 multidex-config.pro 的文件,如下所示:
如果您要指定软件包中的所有类,文件将如下所示:
然后,您可以针对构建类型声明该文件,如下所示:
更多使用说明可以参考官方文档
参考
当我们的Android library是纯代码的情况,如果你只想生成jar包而不想生成aar包,那么可以使用gradle的task来生成
在命令行使用adb logcat命令直接输出日志中文内容显示乱码,原因是中文系统中cmd命令行窗口默认的编码是GBK,而LogCat打印的日志是UTF-8编码,所以adb logcat命令输出的中文内容显示乱码。
修改cmd命令行窗口字符编码即可解决logcat日志中文显示乱码问题:
1.cmd命令行窗口字符编码切换为UTF-8,命令行中执行:chcp 65001
2.修改cmd窗口字体属性,在命令行标题栏上点击右键,选择”属性”->”字体”,将字体修改为”Lucida Console”,点击确定后生效。
修改后logcat -f log.txt方式输出日志到文本文件的乱码问题同样可以解决。
部分字符编码对应代码:
65001——UTF-8
936——简体中文
950——繁体中文
437——美国/加拿大英语
932——日文
949——韩文
866——俄文
cmd窗口字符编码切换回中文:chcp 936
参考
参考
Android有两种类型的API是不能经由SDK访问的。
第一种是位于com.android.internal包中的API。我将称之为internal API。
第二种API类型是一系列被标记为@hide属性的类和方法。
Internal和hidden API的编译时 vs 运行时
当你使用Android SDK进行开发的时候,你引用了一个非常重要的jar文件——android.jar。它位于Android SDK平台的文件夹中(SDK_DIR/platforms/platform-X/android.jar)。这个android.jar移掉了com.android.internal包中所有的类,也移掉了部分标记有@hide的类,枚举,字段和方法。
每个模拟器或真机在运行时都会有一个等同android.jar的东西,叫做framework.jar,它和android.jar等同,而其未移掉internal API和hidden API。当你在设备上启动应用程序时,它将加载framework.jar。
但这样对开发者来说,并不能友好地访问,因此,我将向大家展示不通过反射如何使用这些API。
解决办法如下:
在完整版android.jar下载对应版本的android.jar,然后替换 ${Android Sdk}/platforms/andorid-api/ 下的android.jar即可
参考
主要就是app:tabRippleColor的属性
参考
参考
当父布局设置了padding,而又想子布局在滑动的时候可以无视padding,也就是在padding区域绘制(换句话说就是允许子View滑动的区域包含父容器的padding),此时就需要设置clipToPadding = false,默认是true。
具体可以查看ViewGroup的源码:
应用场景参考
总而言之 如果RecycledView的adapter是一样的话可以考虑共享一个对象池。
比如说: RecycledView嵌套RecycledView,里面的RecycledView大部分都adapter都一样。
注意 如果 LayoutManager是LinearLayoutManager或其子类(如GridLayoutManager) 需要手动开启这个特性:layout.setRecycleChildrenOnDetach(true)
更新于2021/06/21
至于如何获取TextView中的某一行line和指定的span,可以这样操作:
参考
参考
参考
参考
参考
通常用来构建表情emoji字符的Pattern,例如:
参考
一般用于在Dialog中show的时候判断Activity的引用是否有效,例如:
参考
通过tint属性就可以填充颜色了.
adjustViewBounds只有在ImageView一边固定,一边为wrap_content的时候才有意义。设置为true的时候,可以让ImageView的比例和原始图片一样,以达到让图片充满的ImageView的效果。
参考
values-ldrtl/integer.xml定义如下, 其实就是翻转了180°形成镜像
使用方式
图像切换器(ImageSwitcher),用于实现类似于Windows操作系统的“Windows照片查看器”中的上一张、下一张切换图片的功能。在使用ImageSwitcher时,必须实现ViewSwitcher.ViewFactory接口,并通过makeView()方法来创建用于显示图片的ImageView。makeView()方法将返回一个显示图片的ImageView。在使用图像切换器时,还有一个方法非常重要,那就是setImageResource方法,该方法用于指定要在ImageSwitcher中显示的图片资源。
通过setInAnimation和setOutAnimation方法可以设置图片切换时的动画效果
参考
阻止系统恢复Fragment state,在FragmentActivity保存所有Fragment状态前把Fragment从FragmentManager中移除掉。
参考
当我们使用FragmentTransaction的add、hide、show方法进行fragment的添加、隐藏、显示操作的时候并不会执行fragment的onResume和onPause方法,可以通过setMaxLifecycle方法来解决,在ViewPager2里面就使用使用这个来解决.
需要注意的是Activity的布局中内容的高度要固定高度,剩余空间将会透明展示
参考
styles.xml中定义主题
使用示例:
参考
viewstub需要先inflate, 然后再bind到对应的viewStub的layout生成binding类中, 例如:
使用如下:
以ImageView的src属性为例
使用FreeReflection库
这里设置弹窗的层级,数值越大层级就会越高,也就越会浮在最顶端。用到的是一般的应用层级的时候,window的token,也就是我们构造Dialog时候的Context必须是Activity;如果是系统级的类型参数的时候,必须是全局的ApplicationContext才可以,同时还需要获取到系统级应用的权限。比如上面代码中就是系统级层级,需要获取到系统应用权限。
参考
(1) textStyle
代码方式:
(2) style
只需像往常一样在XML layout/your_layout.xml文件中创建TextView
代码方式设置:
参考
关键在于onlyRetrieveFromCache(true),如果本地有缓存那么读取缓存,否则才会从网络获取
注意要在子线程操作
ShareBroadcastReceiver的处理如下:
然后在SecondeActivity中通过setResult返回结果
父Fragment监听
子fragment返回结果
setFragmentResult是系统Fragment类的扩展方法
setOnApplyWindowInsetsListener 方法允许你为视图设置一个回调,以便在窗口插入事件发生时自定义视图的行为或外观。通过这个回调,你可以获取窗口插入的信息,例如状态栏的高度、导航栏的高度等,并根据这些信息来调整视图的布局或样式。
这个方法对于处理窗口插入事件非常有用,无论是为了适应不同设备的屏幕尺寸和系统栏的变化,还是为了实现特定的用户界面效果。
在 Android 5.0 及更早的版本中,View 类没有提供 setOnApplyWindowInsetsListener() 方法。但是,通过使用 Android Support Library 中的 ViewCompat 类,你可以在这些早期版本的 Android 上使用 setOnApplyWindowInsetsListener() 方法。
在刘海屏适配布局内容的时候可以使用,例如:
ConstraintSet类提供了一些常用的方法来设置和修改ConstraintLayout布局中的约束条件。以下是一些常用的方法:
:连接两个视图之间的约束关系。startID和endID分别表示起始视图和结束视图的ID,startSide和endSide表示起始视图和结束视图的边界(例如,ConstraintSet.START表示起始边界,ConstraintSet.END表示结束边界),margin表示边界之间的间距。
:清除指定视图的所有约束关系。
:设置指定视图的可见性。visibility可以是ConstraintSet.VISIBLE、ConstraintSet.INVISIBLE或ConstraintSet.GONE。
:设置指定视图的边界间距。side可以是ConstraintSet.START、ConstraintSet.END、ConstraintSet.TOP或ConstraintSet.BOTTOM。
:设置指定视图的水平偏移。bias的值范围为0.0到1.0,其中0.0表示视图靠近起始边界,1.0表示视图靠近结束边界。
:设置指定视图的垂直偏移。bias的值范围为0.0到1.0,其中0.0表示视图靠近顶部边界,1.0表示视图靠近底部边界。
:设置指定视图的宽高比。ratio是一个字符串,表示宽高比,例如’16:9’。
:设置水平链的样式。chainStyle可以是ConstraintSet.CHAIN_SPREAD、ConstraintSet.CHAIN_SPREAD_INSIDE或ConstraintSet.CHAIN_PACKED。
:设置垂直链的样式。chainStyle可以是ConstraintSet.CHAIN_SPREAD、ConstraintSet.CHAIN_SPREAD_INSIDE或ConstraintSet.CHAIN_PACKED。
:设置指定视图在水平链中的权重。weight表示视图在链中所占的比例。
:设置指定视图在垂直链中的权重。weight表示视图在链中所占的比例。
:设置指定视图的高度。elevation表示视图的高度值。
:方法接受两个参数:viewID表示要设置约束的视图的ID,width表示要设置的宽度值。
方法接受两个参数:viewID表示要设置约束的视图的ID,height表示要设置的高度值。
在Gradle中配置build参数,可以使用buildConfigField来定义一个在代码中可用的常量。
例如清单文件中定义了meta标签如下:
在gradle中可以修改CHANNEL的值
当然在代码中也可以获取到这个CHANNEL的值
参考
资源文件的文件夹命名
参考1
参考2
values-b+zh+Hant+TW:这是 BCP 47 标准中的一种语言标签表示法,用于表示繁体中文(台湾地区)。其中,b 表示 BCP 47 扩展语言标记,zh 表示中文,Hant 表示繁体中文,TW 表示台湾地区。这种表示法在某些特定的场景下使用,例如在 XML 中指定语言标签。
获取系统语言可以这样获取
在 Android 开发中,通常使用 values-zh-rTW 表示繁体中文(台湾地区)的资源文件夹
参考
参考
参考2
推荐使用viewLifecycleOwner,特别是在有调用addToBackStack的场景,fragment从返回栈返回的时候不会触发fragment的onDestory方法,只会触发onDestroyView,而使用viewLifecycleOwner,当触发onDestroyView 之前会销毁使用它所添加的LiveData observe 或者通过它的lifecycle addObserver添加的observer(当触发onDestroyView会触发DefaultLifecycleObserver的onDestory方法回调)
在onCreate的时候设置style
关键代码是下面2行:
参考
FLAG_LAYOUT_IN_SCREEN: 将window放置在整个屏幕之内,无视其他的装饰(比如状态栏)
FLAG_LAYOUT_NO_LIMITS: 允许window扩展值屏幕之外