文章目录
- dialog居中问题
- dialog适配全面屏
- 魅族MX5 显示白色shape无效的问题
- Android studio Connection timed out: connect
- webview页面软键盘弹出不了
- webview一键登录手机QQ失败
- NestedScrollView+RecycleView滚动的问题
- dialog弹窗后导致沉浸栏(statusbar)变黑的问题
- app finish 退出应用重启,application的oncreate方法没有重新执行
- App退到后台,个推发送通知打开不了目标页,打开的是MainActivity的解决办法
- 当RecyclerView遇到Inconsistency detected崩溃时
- 解决部分机型的webview goBack方法返回的页面是空白页面
- URLDecoder: Illegal hex characters in escape (%) pattern
- NestedScrollView嵌套RecyclerView导致快速滚动列表的时候会停留在列表的顶部
- JSONObject的optLong()的坑
- URL中关于空格的编码转换成+或转换成%20的问题
- Android 9 网络适配 network-security-config & cleartextTrafficPermitted
- databinding中的TextView设置margin属性
- Caused by: org.apache.xerces.impl.io.MalformedByteSequenceException: Invalid byte 3 of 3-byte UTF-8
- Android 上出现:Type parameter T has incompatible upper bounds: ViewDataBinding 的问题
- Missing import expression although it is registered
- favicon.ico不存在导致webview#WebViewClient的onReceivedHttpError返回404状态码
- 刘海屏如何全屏让布局延伸到状态栏底下
- androidx.preference.PreferenceScreen 去除左边空白
- The style on this component requires your app theme to be Theme.MaterialComponents
- android 编译突然出错,错误原因 Could not resolve com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+.
- 微信登录,返回-6错误
- 微信取消分享后还是执行成功函数
- Cause: invalid type code: 1C
- ExoPlayerFactory.newSimpleInstance 报错
- exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code 302
- Textview做跑马灯出现抖动问题
- 解决Android10读取不到/sdcard/、/storage/emulated/0/文件的问题
- java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionBaseViewHolder{d29491a position=4 id=-1, oldPos=-1, pLpos:-1 no parent}
- 解决支付宝SDK与友盟推送SDK出现的utdid冲突!
- AndroidStudio Build Output乱码解决
- Android Studio中Junit单元测试使用JSON对象异常的问题
- IntelliJ IDEA 运行项目的时候提示 Command line is too long 错误
- permission denied for window type 2002解决方法
- Lint found fatal errors while assembling a release target.
- error: style attribute 'attr/colorPrimary (:attr/colorPrimary)' not found.
- Android Error:Execution failed for task ':app:compileDebugJavaWithJavac' 解决方案
- 关于unbindService未调用onServiceDisconnected
- android.util.AndroidRuntimeException: requestFeature() must be called before adding content 异常处理
- Error running app: Default Activity Not Found
- 解决项目中使用kotlin不能直接引用xml中id
- Could not find org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.20.
- warn: multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?
- BottomSheetXXX实现下滑关闭菜单踩坑记
- 小米手机使用NinePatchDrawable会出现线条的问题解决
- ClickableSpan事件和View.onClick()事件冲突
- BitmapFactory.decodeResource为null的处理方法之一
- FloatingActionButton图标颜色无法修改
- 导出ANR traces 文件(解决无权限、Permission denied)
- 解决ViewPager2嵌套ViewPager2,导致内部ViewPager滑动无效的问题
- 解决mac下AS的git log乱码问题
- 点9图的非内容区域也是会占用实际宽高的.
- 全屏时导致软键盘弹起会遮挡布局内容处理
- 使用canvas.drawRoundRect()时,解决四个圆角的线比较粗的问题
- java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException解决办法
- TabLayout的selectTab无效
- DialogFragment的一些设置项以及坑
- ImageView的maxHeight和minHeight无效问题
- Fragment使用的各种奔溃异常
- ConstraintLayout maxWidth无效问题
- resolveActivity返回null问题
- 关于Context.startForegroundService() did not then call Service.startForeground()的解决办法
- java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
dialog居中问题
android 5.1.1 vivo x7手机弹出Dialog的时候,根布局必须要设置 android:layout_gravity="center"
属性,布局内容才会居中显示,我自己手机是android8.1.0的,不用设置也可以自动居中显示,坑啊…
2019/03/19
dialog适配全面屏
今天测试提了个bug,在刘海屏的手机上弹窗,在底部蒙层没有遮住下面的显示区域,同时弹窗后退到后台再回来会发现dialog样式变了连同下面的Activity的布局也变了. 解决办法如下:
<style name="myDialog" parent="@android:style/Theme.Dialog">
<!--Dialog的windowFrame框为无-->
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@color/full_transparent</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">@null</item>
<!--背景是否模糊显示-->
<item name="android:backgroundDimEnabled">true</item>
<!--**重点在这下面3句**-->
<!--状态栏透明化,解决dialog显示的时候状态栏是黑色的,让dialog布局内容可延伸到状态栏-->
<item name="android:windowTranslucentStatus">true</item>
<!--状态栏颜色设置成透明-->
<item name="android:statusBarColor">@android:color/transparent</item>
<!--导航透明化,解决dialog显示的时候底部有空白,让dialog布局可延伸到导航栏-->
<item name="android:windowTranslucentNavigation">true</item>
</style>
然后在自定义的dialog上使用该样式
public class TabSelectDialog extends Dialog {
public TabSelectDialog(@NonNull Context context) {
super(context,R.style.myDialog); //这里使用样式
setContentView(R.layout.dialog_tab_select);
}
}
还有一个问题就是,虽然布局中已经设置match_parent全屏模式,但是弹出的dialog的布局内容却不是全屏的.因此在自定义的dialog中重写onStart,设置dialog的宽高为全屏模式
@Override
protected void onStart() {
super.onStart();
Window window = getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = getContext().getResources().getDisplayMetrics().heightPixels;// 用MATCH_PARENT,状态栏和导航栏会覆盖不了
window.setAttributes(lp);
}
2019/03/22
魅族MX5 显示白色shape无效的问题
该手机必须要设置stroke属性,否则无效
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"/>
<corners android:radius="50dp"/>
<!--魅族mx5必须要弄这个属性,否则看不到效果-->
<stroke android:color="@color/white" android:width="1px"/>
</shape>
2019/03/25
Android studio Connection timed out: connect
手动注释掉下面这2句
2019/03/27
webview页面软键盘弹出不了
2019/04/02
webview一键登录手机QQ失败
不知道什么时候开始, QQ oauth登陆, 不再让你在网页输入账号密码了. 页面提示正在拉起QQ手机版.然后测试发现点击之后提示qq版本太低,请升级, 一看版本已经是最新的了,这显然有问题.
通过观察webview的shouldOverrideUrlLoading方法返回的url发现,一键登录触发的链接是这样的, 这是在我们的webview加载的苏宁的购物页面中点击qq登录后捕获的url
可见url的schema并不是http或者https开头的链接地址,而是wtloginmqq
,灵机一动,我想到了通过intent来让系统帮我们跳转到QQ, 思路有了,那就干
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//优先判断qq登录协议
if (url.startsWith("wtloginmqq://ptlogin/qlogin")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
//然后才是正常的url判断
if (URLUtil.isNetworkUrl(url)) {
view.loadUrl(url);
return true;
}
return false;
}
ok, 搞定.点击一键登录qq成功后会跳去系统默认的浏览器显示苏宁购物的页面操作.
2019/04/03
NestedScrollView+RecycleView滚动的问题
1.滚动不了
检查RecyclerView的高度是不是设置了match_parent,是的话,修改成wrap_content就好了
2.滚动不灵敏
RecycleView需要设置setNestedScrollingEnabled(false)
3.RecycleView抢占焦点
给RecycleView布局设置android:focusableInTouchMode=“false”
2019/04/17
dialog弹窗后导致沉浸栏(statusbar)变黑的问题
修改dialog的高度,将MATCH_PARENT修改成屏幕的真实高度即可.
@Override
protected void onStart() {
super.onStart();
Window window = getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
lp.height = getContext().getResources().getDisplayMetrics().heightPixels;//高度为真实高度
window.setAttributes(lp);
}
另外,dialog想要状态栏透明,还需要设置这些style
<!--状态栏透明-->
<item name="android:windowTranslucentStatus">true</item>
<!--状态栏颜色设置成透明-->
<item name="android:statusBarColor">@android:color/transparent</item>
2019/04/29
app finish 退出应用重启,application的oncreate方法没有重新执行
finish后加上这句 System.exit(0);退出虚拟机,App的进程就会被杀掉.
App退到后台,个推发送通知打开不了目标页,打开的是MainActivity的解决办法
通常情况下,是根据推送协议构建intent,然后再生成PendingIntent,最后Notification的setContentIntent来设置PendingIntent,当点击通知栏的推送通知就可以直接打开inten对应的Activity了. 但是今天测试发现,如果App退到后台时,只能打开MainActivity的神奇现象…
解决办法,创建一个空白的Activity, 启动模式设置为singleTask, 然后收到推送通知的时候,点击时先跳去该空白的Activity, 将推送协议带过去,统一在这个空白的Activity中处理协议跳转目标页,跳过去之后关闭当前的空白页即可.
代码如下:
@Override
protected void initIntent() {
super.initIntent();
//获取推送协议
String protocol = getIntent().getStringExtra("protocol");
//根据推送协议生成对应的目标页的intent对象
Intent target = PushHelper.getIntent(this, protocol);
//启动目标Activity
startActivity(target);
//关闭当前空白页
finish();
overridePendingTransition(0, 0);
}
2019/05/16
当RecyclerView遇到Inconsistency detected崩溃时
详情
RecyclerView的Adapter里,发生异常的错误代码如下:
public void notifyData(List<PoiItem> poiItemList) {
if (poiItemList != null ) {
mPoiItems.clear();
mPoiItems.addAll(poiItemList);
notifyItemRangeChanged(0, poiItemList.size());
}
}
修复后,运行正常的代码如下:
public void notifyData(List<PoiItem> poiItemList) {
if (poiItemList != null) {
int previousSize = mPoiItems.size();
mPoiItems.clear();
notifyItemRangeRemoved(0, previousSize);
mPoiItems.addAll(poiItemList);
notifyItemRangeInserted(0, poiItemList.size());
}
}
2019/05/25
解决部分机型的webview goBack方法返回的页面是空白页面
我这里遇到的是使用loadDataWithBaseURL方式来加载网页的情况,问题代码如下:
mWebView.loadDataWithBaseURL(url, pcResponse.getResponse(), “text/html”, “UTF-8”, null);
最后一个参数传了null ,查看源码发现他与历史记录有关 ,如果传null,返回历史页面就会看到空白’about:blank’
/**
* @param baseUrl the URL to use as the page's base URL. If null defaults to
* 'about:blank'.
* @param data a String of data in the given encoding
* @param mimeType the MIMEType of the data, e.g. 'text/html'. If null,
* defaults to 'text/html'.
* @param encoding the encoding of the data
* @param historyUrl the URL to use as the history entry. If null defaults
* to 'about:blank'. If non-null, this must be a valid URL.
*/
public void loadDataWithBaseURL(String baseUrl, String data,
String mimeType, String encoding, String historyUrl) {
checkThread();
mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
}
所以只需把最后一个参数填上url即可,例如:
mWebView.loadDataWithBaseURL(url, pcResponse.getResponse(), “text/html”, “UTF-8”, url);
2019/06/03
URLDecoder: Illegal hex characters in escape (%) pattern
2019/06/25
NestedScrollView嵌套RecyclerView导致快速滚动列表的时候会停留在列表的顶部
方式一:
在RecycleView的外包裹一个父布局,添加这几个属性, 这种方式比较暴力,会导致EditText获取不了焦点无法点击.
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:focusable="true"
android:focusableInTouchMode="true">
</android.support.constraint.ConstraintLayout>
然后RecyclerView设置setNestedScrollingEnabled(false);
方式二:
mSearchEdt.clearFocus();//默认清空EditText的焦点
findViewById(R.id.scroll_view).setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mSearchEdt.clearFocus(); //触摸列表的时候,清空EditText的焦点
return false;
}
});
2019/06/27
JSONObject的optLong()的坑
URL中关于空格的编码转换成+或转换成%20的问题
使用android 提供的Uri.encode方法解决,详情
Android 9 网络适配 network-security-config & cleartextTrafficPermitted
databinding中的TextView设置margin属性
报错
Cannot find the setter for attribute ‘android:layout_marginRight’ with parameter type int on android.widget.TextView.
Caused by: org.apache.xerces.impl.io.MalformedByteSequenceException: Invalid byte 3 of 3-byte UTF-8
Android 上出现:Type parameter T has incompatible upper bounds: ViewDataBinding 的问题
Missing import expression although it is registered
favicon.ico不存在导致webview#WebViewClient的onReceivedHttpError返回404状态码
主要是重写 WebViewClient的这3个方法
//禁用favicon.ico请求
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) //5.0
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (!request.isForMainFrame() && request.getUrl().getPath().endsWith("/favicon.ico")) {
try {
//返回一个本地的favicon.ico
return new WebResourceResponse("image/png", null,
new BufferedInputStream(view.getContext().getAssets().open("favicon.ico")));
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (url.toLowerCase().contains("/favicon.ico")) {
try {
return new WebResourceResponse("image/png", null,
new BufferedInputStream(view.getContext().getAssets().open("favicon.ico")));
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
//Android6.0以上404或者500处理
@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
int statusCode = errorResponse.getStatusCode();
if (!request.isForMainFrame() && request.getUrl().getPath().endsWith("/favicon.ico") ) {
Log.e("cys","favicon.ico 请求错误"+errorResponse.getStatusCode()+errorResponse.getReasonPhrase());
}else{
if (404 == statusCode || 500 == statusCode) {
onReceivedError = true;
view.loadUrl("about:blank");// 避免出现默认的错误界面
mUEView.showError();
}
}
}
然后在项目的asserts目录下添加一个favicon.ico文件, 若网页不存在则使用该本地的.
刘海屏如何全屏让布局延伸到状态栏底下
<style name="AppTheme.FullScreen">
<item name="windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<!--允许页面延伸到刘海区域-->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
2020-7-5
androidx.preference.PreferenceScreen 去除左边空白
The style on this component requires your app theme to be Theme.MaterialComponents
Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:248)
at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:222)
at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:150)
at com.google.android.material.internal.ThemeEnforcement.obtainStyledAttributes(ThemeEnforcement.java:81)
at com.google.android.material.button.MaterialButton.<init>(MaterialButton.java:200)
at com.google.android.material.button.MaterialButton.<init>(MaterialButton.java:191)
解决办法
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
改成
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
android 编译突然出错,错误原因 Could not resolve com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+.
2020-7-13
微信登录,返回-6错误
微信取消分享后还是执行成功函数
Cause: invalid type code: 1C
今天在mac上打开AS编译项目出现这个错误,查了下是因为我安装的jdk是14的版本。
解决办法有2种:
1.修改gradle-wrapper.properties中的gradle版本,改为gradle-6.5-all.zip
2.重新下载一个jdk1.8的版本
2020-7-19
ExoPlayerFactory.newSimpleInstance 报错
原因是需要打开对java8的支持,需要在所有依赖ExoPlayer的build.gradle文件里打开对java8的支持,在android闭包中添加以下代码即可
compileOptions {
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
}
exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code 302
Textview做跑马灯出现抖动问题
设置跑马灯效果
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
解决抖动问题,只需要在外面添加一个LinearLayout父布局即可
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingRight="20dp"
app:layout_constraintBottom_toBottomOf="@+id/iv_back"
app:layout_constraintLeft_toRightOf="@+id/iv_back"
app:layout_constraintRight_toLeftOf="@+id/iv_more"
app:layout_constraintTop_toTopOf="@+id/iv_back">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:text="我是标题,让我来回滚起"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
解决Android10读取不到/sdcard/、/storage/emulated/0/文件的问题
原因
Android Q官方文档
Android Q 分区存储
Android Q文件存储机制修改成了沙盒模式,和IOS神似
应用只能访问自己沙盒下的文件和公共媒体文件
对于Android Q以下,还是使用老的文件存储方式
解决办法:
在AndroidManifest.xml 里的application中添加 android:requestLegacyExternalStorage=“true” 临时解决。可以兼容到Android 11。或者targetsdk 降低到29以下。
<application
android:requestLegacyExternalStorage="true">
2020/09/25
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionBaseViewHolder{d29491a position=4 id=-1, oldPos=-1, pLpos:-1 no parent}
原因是RecycleView数据变动(移除和增加)没有保证Adapter中的数据和外部集合中的数据保持一致导致的同步问题.
参考
链接一
链接二
解决支付宝SDK与友盟推送SDK出现的utdid冲突!
AndroidStudio Build Output乱码解决
Android Studio中Junit单元测试使用JSON对象异常的问题
比如:
JSONObject jsonObject = new JSONObject();
报异常:java.lang.RuntimeException: Method put in org.json.JSONObject not mocked. See https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support for details.
但是将测试代码放到设备AndroidTest中,使用JSONObject代码时无异常。
原来,JSON包含在Android SDK中,JUnit单元测试无法使用,会抛异常;但可以在AndroidTest中使用,如果要在Junit中使用,需要在App或Library项目的build.gradle中添加依赖:
testCompile files('libs/json-20180813.jar')
这个jar包可以在gradle的缓存中提取出来
IntelliJ IDEA 运行项目的时候提示 Command line is too long 错误
在执行单元测试的时候提示:
Command line is too long. Shorten command line for Application or also for Spring Boot default configuration.
解决办法如下图所示:
permission denied for window type 2002解决方法
在android8.0之后,WindowManager.LayoutParams的type需要这样设置
// 设置窗体显示类型
WindowManager.LayoutParams layoutParams= new WindowManager.LayoutParams();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type =WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
}
else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
ps:在Android6.0之前,如果要弹出全局悬浮窗,只需要在AndroidManifest.xml中申请如下权限即可。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
但是从Android6.0开始,不仅需要上述权限,还需要动态申请此权限,用户手动开启才行。
处理方法如下:
if (Build.VERSION.SDK_INT >= 23) { // Android6.0及以后需要动态申请权限
if (!Settings.canDrawOverlays(mContext)) {
//启动Activity让用户授权
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1010);
} else {
// 弹出悬浮窗
}
} else {
// 弹出悬浮窗
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1010) {
if (Build.VERSION.SDK_INT >= 23) { // Android6.0及以后需要动态申请权限
if (Settings.canDrawOverlays(mContext)) {
// 弹出悬浮窗
} else {
Toast.makeText(mContext, "not granted permission!", Toast.LENGTH_SHORT);
}
}
}
}
Lint found fatal errors while assembling a release target.
To proceed, either fix the issues identified by lint, or modify your build script as follows:
…
android {
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
}
…
意思是可以通过lintOptions来忽略错误:
lintOptions {
// 遇到lint检查错误是否要终止构建,这里设置false表示不终止
abortOnError false
// 是否将警告当作错误来处理
warningsAsErrors false
// 是否检查新API
check 'NewApi'
}
error: style attribute ‘attr/colorPrimary (:attr/colorPrimary)’ not found.
添加依赖即可
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}
Android Error:Execution failed for task ‘:app:compileDebugJavaWithJavac’ 解决方案
如果是mac或者Linux系统,那么在控制台输入 ./gradlew compileDebugJavaWithJavac --stacktrace 就可以查看是什么原因造成的错误,如果不够权限,那么需要给gradlew文件添加执行权限 chmod u+x gradlew
如果是windows系统,那么使用gradlew.bat compileDebugJavaWithJavac --stacktrace
关于unbindService未调用onServiceDisconnected
1、onServiceDisconnected() 在连接正常关闭的情况下是不会被调用的.
2、该方法只在Service 被破坏了或者被杀死的时候调用. 例如, 系统资源不足, 要关闭一些Services, 刚好连接绑定的 Service 是被关闭者之一, 这个时候onServiceDisconnected() 就会被调用.
android.util.AndroidRuntimeException: requestFeature() must be called before adding content 异常处理
Error running app: Default Activity Not Found
解决项目中使用kotlin不能直接引用xml中id
需要添加kotlin-android-extensions插件
Could not find org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.20.
把jre7改成jdk7就ok了
warn: multiple substitutions specified in non-positional format; did you mean to add the formatted=“false” attribute?
BottomSheetXXX实现下滑关闭菜单踩坑记
小米手机使用NinePatchDrawable会出现线条的问题解决
如下图所示:
很明显大按钮会看到有线条,而下面的方式是直接在xml种指定.9图的是没有问题的.
问题代码:
val ninePatchDrawable =
ResourcesCompat.getDrawable(resources,R.drawable.ic_shape_nine_big,context.theme) as NinePatchDrawable
上面的代码是直接通过getDrawable的方式加载存放在drawable-xxxhdpi文件夹内的.9图然后强转成NinePatchDrawable的
正确的代码:
val ninePatchDrawable = BitmapFactory.decodeResource(resources, R.drawable.ic_shape_nine_big).run {
NinePatchDrawable(resources, this, ninePatchChunk, Rect(), null)
}
通过构造方法NinePatchDrawable来创建NinePatchDrawable才是正道.
有人会说拿到NinePatchDrawable有什么用?
我们可以通过代码调用控件的setBackground方法传递一个NinePatchDrawable, 或者通过ninePatchDrawable的draw方法将.9图绘制到canvas上,将ninePatchDrawable转成bitmap来进行各种操作等等.
ClickableSpan事件和View.onClick()事件冲突
BitmapFactory.decodeResource为null的处理方法之一
FloatingActionButton图标颜色无法修改
导出ANR traces 文件(解决无权限、Permission denied)
解决ViewPager2嵌套ViewPager2,导致内部ViewPager滑动无效的问题
思路就是在内部的ViewPager2中嵌套一个父布局,然后在父布局中处理滑动冲突问题, 我这里写了一个工具类
class ViewPager2ScrollableHost private constructor(
private val parent: ViewGroup,
private val childViewPager: ViewPager2,
context: Context
) {
private var touchSlop = 0
private var initialX = 0f
private var initialY = 0f
companion object {
@JvmStatic fun newInstance(
parent: ViewGroup,
childViewPager: ViewPager2
): ViewPager2ScrollableHost {
return ViewPager2ScrollableHost(parent, childViewPager, parent.context)
}
}
// 获取父的ViewPager2
private val parentViewPager: ViewPager2?
get() {
var v: View? = parent
while (v != null && v !is ViewPager2) {
v = v.parent as? View
}
return v as? ViewPager2
}
private fun canChildScroll(orientation: Int, delta: Float): Boolean {
val direction = -delta.sign.toInt()
return when (orientation) {
0 -> childViewPager.canScrollHorizontally(direction)
1 -> childViewPager.canScrollVertically(direction)
else -> throw IllegalArgumentException()
}
}
init {
touchSlop = ViewConfiguration.get(context).scaledTouchSlop
}
fun onInterceptTouchEvent(e: MotionEvent): Boolean {
handleInterceptTouchEvent(e)
return false
}
private fun handleInterceptTouchEvent(e: MotionEvent) {
val orientation = parentViewPager?.orientation ?: return
// Early return if child can't scroll in same direction as parent
if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
return
}
if (e.action == MotionEvent.ACTION_DOWN) {
initialX = e.x
initialY = e.y
// down事件一定要禁掉父的ViewPager2的拦截
parent.requestDisallowInterceptTouchEvent(true)
} else if (e.action == MotionEvent.ACTION_MOVE) {
val dx = e.x - initialX
val dy = e.y - initialY
val isVpHorizontal = orientation == ViewPager2.ORIENTATION_HORIZONTAL
// assuming ViewPager2 touch-slop is 2x touch-slop of child
val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1f
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
if (scaledDx > touchSlop || scaledDy > touchSlop) {
if (isVpHorizontal == (scaledDy > scaledDx)) {
// Gesture is perpendicular, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
} else {
// Gesture is parallel, query child if movement in that direction is possible
if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
// Child can scroll, disallow all parents to intercept
parent.requestDisallowInterceptTouchEvent(true)
} else {
// Child cannot scroll, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
}
}
}
使用方法如下:
public class MyScrollViewpager extends FrameLayout {
public MyScrollViewpager(Context context) {
this(context, null);
}
public MyScrollViewpager(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyScrollViewpager(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mPageChangeCallback = new ViewpagerOnPageChangeCallback();
// 创建子的ViewPager2
mViewPager2 = new ViewPager2(context);
mViewPager2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mViewPager2.setOffscreenPageLimit(1);
mViewPager2.registerOnPageChangeCallback(mPageChangeCallback);
// 添加子的ViewPager2
addView(mViewPager2);
// 关联当前容器和子的ViewPager2
mViewPager2ScrollableHost = ViewPager2ScrollableHost.newInstance(this, mViewPager2);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 交给ViewPager2ScrollableHost处理事件
mViewPager2ScrollableHost.onInterceptTouchEvent(ev);
return super.onInterceptTouchEvent(ev);
}
}
除了上面的方式, 还可以这样处理,在MyScrollViewpager的dispatchTouchEvent做处理
//上一次x坐标
private float beforeX;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!getViewPager2().isUserInputEnabled()) {
return super.dispatchTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
beforeX = ev.getX();
// down事件需要禁掉父ViewPager2的拦截
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
float motionValue = ev.getX() - beforeX;
if ("只支持向左滑动") {
if (motionValue > 0) {
//右滑,让外部的父ViewPager2处理
getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
} else if ("支持向右滑动") {
if (motionValue < 0) {
//左滑,让外部的父ViewPager2处理
getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
}
beforeX = ev.getX();
break;
default:
break;
}
// 注意要返回super,否则事件不会分发到子ViewPager2
return super.dispatchTouchEvent(ev);
}
解决mac下AS的git log乱码问题
解决办法很简单
点9图的非内容区域也是会占用实际宽高的.
点9图的上边和左边是限定拉伸区域,下边和右边是限定内容显示区域. 在上图中内容的限制区域刚好是白色的圆角矩形内容,而用红色框框框住的这些距离其实是非内容区域, 但是如果使用该点9图的话,这些非内容区域其实也是占据空间的,也就是说就算你布局中没有设置任何的margin值,但是任然会看到该View距离四周有一点距离.
全屏时导致软键盘弹起会遮挡布局内容处理
在Android实现了沉浸式功能后,在有输入框的界面,当点击输入框弹起输入法时,输入法遮挡住了输入框,或者输入框在底部并没有随着输入法弹起而弹起。虽然Activity设置了
android:windowSoftInputMode="adjustResize"
解决方法:
在EditText的根布局添加android:fitsSystemWindows="true"
代码即可解决。
注意:
必须在EditText的根布局添加,如果不是根布局,在其它位置或节点添加,界面会多出一块布局 这块布局和顶部状态栏高度一样 颜色可能也一样。
另一种办法就是不设置全屏,通过修改状态栏颜色改成和布局的颜色一样,这样也可以起到状态栏颜色和布局颜色一样的效果.
使用canvas.drawRoundRect()时,解决四个圆角的线比较粗的问题
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException解决办法
把换jdk版本,jdk8 jdk7即可。
TabLayout的selectTab无效
DialogFragment的一些设置项以及坑
1.show和showNow的注意点
首先说一下结论:在使用过程中尽量使用showNow
现在我们知道:
firstDialog.show(supportFragmentManager, "First")
和
firstDialog.showNow(supportFragmentManager, "First")
都可以展示dialog,
但在使用它们过程中还有需要注意的地方:
show要比showNow稍微“慢”一点,这导致调用show了后,立刻修改dialog中的view(例如textView修改字符内容)会崩溃,而showNow不会
先在FirstDialogFragment中添加方法:
fun setContent(text: String) {
tv_content.text = text
}
以下代码会崩溃:
val firstDialog = FirstDialogFragment()
firstDialog.show(supportFragmentManager, "First")
firstDialog.setContent("Hello")
以下代码则正常执行(对话框内容被修改为Hello):
val firstDialog = FirstDialogFragment()
firstDialog.showNow(supportFragmentManager, "First")
firstDialog.setContent("Hello")
展示弹窗后fragment对象会添加到activity,showNow会在弹窗dismiss消失后移除fragment,show不会移除。
(以前同一个对象非连续地调用两次show会崩溃,现在不会了,可能是google更新了,使show也在弹窗消失后移除了)
2.不可连续地调用show或者showNow
这个“连续”是指在弹窗还没有消失的时候再次调用
原因其实在2中说了,展示弹窗后fragment对象会添加到activity,而同一个fragment只能添加一次,所以连续调用会崩。
一下代码会崩溃:
firstDialog.showNow(supportFragmentManager, "First")
firstDialog.showNow(supportFragmentManager, "First")
firstDialog.show(supportFragmentManager, "First")
firstDialog.show(supportFragmentManager, "First")
避免方法也很简单,用isResumed来判断当前dialog是否正在展示
private fun showFirstDialog() {
if (firstDialog.isResumed) {
return
}
firstDialog.showNow(supportFragmentManager, "First")
}
当然也可以不直接return,可以做一些其他业务处理
3.使Dialog不可消失
(1)点击返回键弹窗区域外均不消失
必须在showNow之后才有效
firstDialog.showNow(supportFragmentManager, "First")
firstDialog.dialog?.setCancelable(false) //必须在showNow之后才有效
任何时候都生效
firstDialog.isCancelable=false
(2)点击弹窗区域外不消失 点击返回键消失
firstDialog.dialog?.setCanceledOnTouchOutside(false)
ImageView的maxHeight和minHeight无效问题
必须要结合adjustViewBounds使用才行
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:maxHeight="164dp"
android:minHeight="136dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_party_matching_bg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Fragment使用的各种奔溃异常
1. commit already called
2. Fragment already added
3. This transaction is already being added to the back stack
4. Can not perform this action after onSaveInstanceState
5. FragmentManager is already executing transactions
ConstraintLayout maxWidth无效问题
使用app:layout_constraintWidth_max代替
参考
resolveActivity返回null问题
通常会出现在获取系统的Activity, 例如跳去系统的浏览器等等. 原因:Android 30 及以上就⽆法使⽤该api了。
这里以打开系统浏览器的intent为例,在清单文件中添加:
<!-- Android 11 包可见性 添加意图-->
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="*"/>
</intent>
</queries>
关于Context.startForegroundService() did not then call Service.startForeground()的解决办法
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
产生原因:
FragmentManager 在保存状态后调用了 show(),通常发生在配置更改或应用进入后台时。这会导致 IllegalStateException,因为在 onSaveInstanceState 之后,Fragment 事务被限制,以防止状态不一致。
解决办法:
在调用 show() 之前检查 isStateSaved。如果状态已经保存,则使用 commitAllowingStateLoss(),这样可以在允许状态丢失的情况下显示对话框,避免崩溃。
if (!fragment.childFragmentManager.isStateSaved) {
myDialogFragment.show(fragment.childFragmentManager, MY_DIALOG_TAG)
} else {
// 在状态已保存的情况下允许 StateLoss 提交
fragment.childFragmentManager.beginTransaction()
.add(myDialogFragment, MY_DIALOG_TAG)
.commitAllowingStateLoss()
}