Bug汇总
1.EditText光标不显示
不知道为什么EditText光标一直不显示,查询之后发现是因为textCursorDrawable这个属性不是null。
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入内容"
app:layout_constraintTop_toBottomOf="@id/button2"
android:textCursorDrawable="@color/colorPrimaryDark"
/>
更改之后,想着继续改进,想更改光标的颜色。这样需要自己新定义一个shape。在drawable下新建xml文件
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="1dp" />
<solid android:color="#000000" />
</shape>
更改textCursorDrawable。
android:textCursorDrawable="@drawable/cursor_color"
效果图:(正常的光标在我这里是红色的)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190702171904831.png
2.遇到一个问题(above属性的问题)
我的listView自动与下面的layout对齐,不是出现在最上面的。
效果如图:
那我更改一下让他出现在最上面被,我增加一行属性。
android:layout_alignParentTop="true"
这样会出现以下效果,
会发现课程列表的下面多出了一块,仍然是与下面的layout对齐,终于发现问题,应该是我设置了layout_above,那么我去掉这个属性呢。
效果如图:
看着好像是ok了,但我的课程列表中的课比较多的时候就会有问题。会发现下面的layout会在这个课程列表中的课的上面,所以不能去掉这个above。
那么如何解决呢
解决办法:外层套一个layout,让这个layout的height是match_parent的,然后在这个layout里above下面的layout,同时不给这个layout设置背景颜色,这样视觉效果就不会多显示一块了。
效果图:
3.Can’t toast on a thread that has not called Looper.prepare()
在子线程中弹出Toast,会报错:java.lang.RuntimeException: Can’t toast on a thread that has not called Looper.prepare()。
解决方法:在子线程中更新UI
4.解决button的重复点击
1.正常思路就是封装一个listener,处理点击间隔判断。简单来说就是当前的时间与上一次点击的时间去比较,如果时间差大于我们设置的时间差,即可继续点击。
public abstract class CustomClickListener implements View.OnClickListener {
private long mLastClickTime;
private long timeInterval = 1000L;
public CustomClickListener() {
}
public CustomClickListener(long interval) {
this.timeInterval = interval;
}
@Override
public void onClick(View v) {
long nowTime = System.currentTimeMillis();
if (nowTime - mLastClickTime > timeInterval) {
// 单次点击事件
onSingleClick();
mLastClickTime = nowTime;
} else {
// 快速点击事件
onFastClick();
}
}
protected abstract void onSingleClick();
protected abstract void onFastClick();
}
在Activity中使用
btTest.setOnClickListener(new CustomClickListener() {
@Override
protected void onSingleClick() {
Log.d("xxx", "onSingleClick");
}
@Override
protected void onFastClick() {
Log.d("xxx", "onFastClick");
}
});
或者另一种代码思路
public abstract class OnMultiClickListener implements View.OnClickListener{
// 两次点击按钮之间的点击间隔不能少于1000毫秒
private static final int MIN_CLICK_DELAY_TIME = 1000;
private static long lastClickTime;
public abstract void onMultiClick(View v);
@Override
public void onClick(View v) {
long curClickTime = System.currentTimeMillis();
if((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
// 超过点击间隔后再将lastClickTime重置为当前点击时间
lastClickTime = curClickTime;
onMultiClick(v);
}
}
}
在activity中这样使用
btn.setOnClickListener(new OnMultiClickListener() {
@Override
public void onMultiClick(View v) {
// 进行点击事件后的逻辑操作
}
});
5.switch case出现Constant expression required
switch case支持的类型:byte,short,char,int,枚举类型,java.lang.String,由于使用了Integer于是会出现这个问题。
6.返回数据给上一个Activity
总能遇到我在这个Activity2中提交了数据到后台,之后 finish该Activity,就会后退到栈中的前一个Activity(Activity1),然而在这个Activity1中数据就没有更新,需要手动下拉刷新下才会更新。这是因为没有写startActivityForResult。
对应前面说的问题,我在Activity2中执行完提交数据操作,就先执行setResult,之后在执行finish函数,这时Activity1就会回调OnActivityResult,此时就可以执行一些操作,比如更新下数据,重新去后台请求数据。
1)第一个活动传递数据
在活动跳转时写startActivityForResult,该方法可以在活动销毁的时候返回一个结果给上一个活动。
Intent intent = new Intent(this, SonCourseEditActivity.class);
startActivityForResult(intent, 110);
2)第二个活动中使用setResult方法
在点击这个button的时候会执行以下操作
首先将数据存储至Intent,然后,使用setResult()方法,该方法接收两个参数,第一个参数用于向上一个活动返回处理结果,一般有RESULT_OK\RESULT_CANCELED。第二个参数时将带有数据的intent传入,然后finish销毁当前活动。
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_change_son_course:
Intent intent = new Intent(this, CourseTestActivity.class);
intent.putExtra("index", sonCourseIndex);
//其他操作
...
setResult(RESULT_OK, intent);
finish();
break;
}
}
setResult源码。
/**
* Call this to set the result that your activity will return to its
* caller.
*
* <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, the Intent
* you supply here can have {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
* Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
* Intent.FLAG_GRANT_WRITE_URI_PERMISSION} set. This will grant the
* Activity receiving the result access to the specific URIs in the Intent.
* Access will remain until the Activity has finished (it will remain across the hosting
* process being killed and other temporary destruction) and will be added
* to any existing set of URI permissions it already holds.
*
* @param resultCode The result code to propagate back to the originating
* activity, often RESULT_CANCELED or RESULT_OK
* @param data The data to propagate back to the originating activity.
*
* @see #RESULT_CANCELED
* @see #RESULT_OK
* @see #RESULT_FIRST_USER
* @see #setResult(int)
*/
public final void setResult(int resultCode, Intent data) {
synchronized (this) {
mResultCode = resultCode;
mResultData = data;
}
}
3)第一个活动中写onActivityResult()方法
我们是startActivityForResult启动的第二个活动,于是,第二个活动在销毁后,会回调上一个活动的onActivityResult()。
重写onActivityResult()函数。第一个参数是在启动活动时传入的请求码,第二个参数是返回数据是传入的处理结果。第三个参数是携带返回数据的Intent。由于在一个活动中可能有很多次使用startActivityForResult,于是首先需要判断请求码,之后再判断处理结果。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch (requestCode){
case 110:
if (resultCode == RESULT_OK){
int index = intent.getIntExtra("index" , -1);
//其他操作
...
}
break;
}
}
总结
1.ConstraintLayout无法让一个子控件在父容器的最右侧。如果是RelativeLayout就可以做到了。
2. listView中的内容一页显示不下,同时也无法继续向下拉动。ConstraintLayout无法向下滑动?还是应该设置一个属性。(解决:需要在外面嵌套一个ScrollerView就可以滑动)
3.不能让一个layout below listView,不过可以让这个listView above 这个layout。因为listView的长度不是固定的。这样就可以实现不用看完listView中的值,就可以点击下面layout中的控件。
4. headerView中的控件没有与listView中的子Item对齐,同时在Item的xml文件的最外层layout加margin无用,要在layout里面没有对齐的那个控件加margin。