1. ViewPager中如果有页面要显示超出界面的部分,就是clipChildren = false,这时候设置了滑动效果,即 mViewPager.setPageTransformer(false, new ScaleTransformer(), ViewCompat.LAYER_TYPE_NONE);第三个参数要关掉硬件加速,要不然,滑动时,clipChildren = false会失效。
2. TabLayout 会有默认的padding,通过app:tabPaddingEnd=“0dp”, app:tabPaddingStart="0dp"能去掉左右的padding,但是上下还是没有办法解决,虽然有提供属性app:tabPaddingTop=“0dp”,app:tabPaddingBottom=“0dp”,但是设置无效。如果自定义tab样式,需要设置tabMinWidth = 0
3. android seekbar 增加边距paddingstart 不要用paddingleft,要不然没效果。多个seekbar在同一个ViewGroup时,如果拖动某一个,其他的seekbar会响应setPressed(),会出现其他seekbar滑片被点击了的效果,也就是滑动一个,其他几个滑片都出现了放大的效果,是因为ViewGroup做了事件分发,看代码
ViewGroup
@Override
protected void dispatchSetPressed(boolean pressed) {
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = 0; i < count; i++) {
final View child = children[i];
// Children that are clickable on their own should not
// show a pressed state when their parent view does.
// Clearing a pressed state always propagates.
if (!pressed || (!child.isClickable() && !child.isLongClickable())) {
child.setPressed(pressed);
}
}
}
如果要去掉,只要设置 android:clickable="true"即可。就不会分发给子View了。
4. 禁止软键盘自动弹出,EditText父布局中添加android:focusable="true"和android:focusableInTouchMode=“true”
5. JavaX中的类无法导包的问题,比如:AbstractProcessor,需要新建一个Java library模块,然后在这个模块里面实现注解器,android工程没法引用javax中的类,只有Java library这个模块才能引用。
6. Android studio 开启编译期debug,在实现自定义注解时,生成Java文件,需要开启debug调试程序运行是否正确,,说一下怎么开启编译时debug:
然后将配置命令行添加到gradle.properties里面
然后开启debug,就可以在注解器里面打断点了,编译时,就可以调试了。
6. ScrollView里面嵌套recyclerview会导致焦点在recyclerview上,会自动定位到recyclerview的位置,为了不滚动界面需要在布局顶层里面找一个view来获取焦点,添加
android:focusable="true"
android:focusableInTouchMode="true"
7. 新建一个Android项目时,把com.android.tools.build:gradle:3.0.0的版本改低了,改成3.0以下,重新编译会报finished with non-zero exit value 1 错误,告诉你某个属性找不到。finished with non-zero exit value 1这个错误经常会出现,记录下,遇到再补充。
8. fastjson解析私有属性时,需要设置set,get方法,不然没法解析,Gson就没这个问题
9. retrofit使用时发现@Filed与@Body上传的参数格式不一样,这其实是application/x-www-from-urlencoded与 application/json的区别,@Filed是以键值对的格式上传数据,key1=value1&key2=value2,而@Body是以json格式上传的{“key”: “value”},两者不一样,要看服务端怎么解析数据的。
10CoordinatorLayout里面的recyclerview再嵌套recyclerview会出现滑动冲突,需要在最里面的recyclerview设置setNestedScrollingEnabled(false)
11 dialog 显示的时候会出现间距没法填满布局,设置 getWindow().setBackgroundDrawable(null);
12 CoordinatorLayout 滑动导致JNI DETECTED ERROR IN APPLICATION: can’t call void android.view.View.setElevation(float) on null obj崩溃
<android.support.design.widget.AppBarLayout
。。。。
android:stateListAnimator="@null"
。。。
>
13 做一个webview截图的功能的时候遇到一个问题,为了能够截取完整的内容,在外面套了个linearlayout和nestscrollview,LinearLayout是webview的父容器,然后H5内容里面有动态图表,导致在调用linearlayout的draw(cavans)的方法去绘图的时候,这些动态图表绘制不出来,webview里面的其他内容没有问题,就动态图表有问题,然后查了下,说是硬件加速的问题,然后我把webview硬件加速关了,果然好了。然而。。。在Android 10上不管用,鼓捣了半天也没找到解决办法,但是知道肯定跟硬件加速有关系,就在代码里面尝试去关闭硬件加速,发现一个奇葩的现象,要在webview的pagefinish()方法里面加才有作用。。。完全不知道为什么,webview的绘制没有去了解过,这里记下,待查。
14 Glide加载图片的时候报了错You cannot start a load for a destroyed activity
我在一个dialog里面加载了一张图片,奇怪的是我做了activity是否销毁的判断,但是还是崩了,我们都知道dialog的context必须是一个activity,所以在Glide加载之前我加了isDestory()的判断,不管用。调试的时候发现从dialog类getcontext()得到的对象不是我们传入的activity而是一个ContextThemeWrapper,原来在dialog构造器里面并不是直接使用activity而是包了一层,所以直接getcontext得到的就不是传入的activity。
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == ResourceId.ID_NULL) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}
......}
而我在加载图片之前只做了context是否是activity的判断,如果不是activity就直接加载了,没有判断是否是ContextWrapper的判断,而Glide在加载之前却做了一层判断,如下
public RequestManager get(Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
如果context是一个Wrapper就会递归去找wrapper真正代理的对象,对于dialog的context来说,其代理的就是activity,所以glide最后还是会拿activity去加载,如果这个时候activity销毁了,就会出问题。所以在判断是否能加载图片之前要多加一层判断
public static boolean isLoadEnable(Context context) {
if (context == null) {
return false;
} else if (context instanceof Application) {
return true;
} else if(context instanceof Activity){
Activity activity = (Activity)context;
return isLoadEnable(activity);
} else if(context instanceof ContextWrapper){
return isLoadEnable(((ContextWrapper)context).getBaseContext());
}else {
return false;
}
}
public static boolean isLoadEnable(Activity activity) {
if (activity == null) {
return false;
} else {
boolean destroyed = Build.VERSION.SDK_INT >= 17 && activity.isDestroyed();
return !destroyed && !activity.isFinishing();
}
}
15 ScrollView里面嵌套ConstrainLayout会导致anr,不只是子布局不行,就连子布局里面存在ConstrainLayout也不行,也就是说scrollview的子布局和间接子布局都不能有ConstrainLayout。奇怪的是在一些手机上表现的特别明显,有些手机上感觉没什么影响,网上也有人遇到过这种情况https://stackoverflow.com/questions/53046700/constraintlayout-crash-with-stackoverflowerror
16 今天遇到一个kotlin很有意思的问题,看代码
fun testLet(str: String?,str2:String?) {
str?.let {
Log.d("testLet", "非空")
} ?: let {
Log.d("testLet", "空")
}
}
我一直以为kotlin的?.let与?:let是一个if else的关系,翻译成Java就是
if(str!=null){
Log.d("testLet", "非空")
}else{
Log.d("testLet", "空")
}
事实上通过反编译也确实是这样的
public final void testLet(@Nullable String str, @Nullable String str2) {
if (str != null) {
Log.d("testLet", "非空");
} else {
MainActivity it = (MainActivity)this;
Log.d("testLet", "空");
}
}
我一直以为?.let的判断的前置条件是str是否为空,只会走上面let的其中一个作用域,直到今天我写了个这样的代码(逻辑类似)
fun testLet(str: String?,str2:String?) {
str?.let {
Log.d("testLet", "非空")
str2//并不是想返回str2,可能这里是一个表达式,而这个表达式的值是空
} ?: let {
Log.d("testLet", "空")
}
}
testLet("test",null)
然而这个输出却是
testLet: 非空
testLet: 空
居然都输出了,原来let的最后一行是返回值还能作用于后面的?:let空判断。反编译一下
public final void testLet(@Nullable String str, @Nullable String str2) {
if (str != null) {
Log.d("testLet", "非空");
if (str2 != null) {
return;
}
}
MainActivity it = (MainActivity)this;
Log.d("testLet", "空");
}
所以?.let与?:let作为空判断不是互斥关系的还要看let的返回值,平时还是要注意点,否则,这些小细节还是不容易排查。
17:groovy插件与Android模块不兼容,只能放到Java 模块中。
18Recyclerview 高度 WRAP_CONTENT导致卡顿
19 Textview 频繁设置settext导致卡顿