DialogFragment在新建后,即便设置布局宽度为MATCH_PARENT,实际展示出来的效果还是与屏幕有一定的边距,想要使宽度充满屏幕,需要进行以下操作
1. 在DialogFragment的onStart方法中,加入如下代码:
dialog?.setCancelable(false)
dialog?.setCanceledOnTouchOutside(false)
val dm = DisplayMetrics()
activity?.windowManager?.defaultDisplay.getMetrics(dm)
dialog?.window?.setLayout(dm.widthPixels * 1, dm.heightPixels * 1)
2. 在res/values/styles.xml文件中,新增如下样式:
<style name="MatchWidthDialog" parent="@style/Theme.AppCompat.Dialog">
<item name="android:windowCloseOnTouchOutside">true</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
3. 在DialogFragment的onCreate方法中,加入如下代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.MatchWidthDialog)
}
RecyclerView中notifyItemRemoved的一个坑
我们为了移除RecycleView的某一项,会用RecycleView的notifyItemRemoved(int position)方法,但是需要注意的是:
1、用该方法之后并不会刷新Item,也就是说不会重新bind数据,那么position也就没有刷新,每个Item对应的position还是原来的那个,那就会有问题,比如现在只剩下3个Item,而我们点击删除最后一个Item的时候,它的position是原来的position4,那么实际上就是调用RecycleView的notifyItemRemoved(4),就会出现越界。
那我们该怎么做呢?
1、删除之后重新:notifyDataSetChanged();,但是这样就没有删除动画。
2、使用notifyItemRangeChanged(int positionStart, int itemCount)
这个方法,是通知所有观察者: 从positinStart开始的itemCount这些个item已经改变了,与notifyItemRangeChanged(position, itemCount, null)等价
positionStart : 是从界面哪个位置的Item开始变化,比如你点击界面上的第二个ItemView positionStart是1
itemCount : 是已经发生变化的item的个数(包括自己,即正在点击这个),比如,你点击界面上的第二个ItemView,position [1,9] 发生变化,共计9个,因此我们计算是list.size() - position
此时使用:
notifyItemRemoved(position);
notifyItemRangeChanged(position, mList.size() - position);
注意如果有headView的话还需要将position加上对应的headView数目,比如有一个headView,那么就需要:
notifyItemRemoved(position + 1);
notifyItemRangeChanged(position + 1, mList.size() - position);
1. Unable to add window --token null is not valid; is your activity running
$BadTokenException: Unable to add window --
token null is not valid; is your activity running
E/AndroidRuntime(1412): at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
......
该异常多见于Popup Widow组件的使用中抛出
原因:错误在PopupWindow.showAtLocation(findViewById(R.id.main), Gravity.BOTTOM,0,0); popwindow必须依附于某一个view,而在oncreate中view还没有加载完毕,必须要等activity的生命周期函数全部执行完毕,你需要依附的view加载好后才可以执行popwindow。
解决办法:showAtLocation()函数可以这样改
//修正后代码
findviewById(R.id.mView).post(new Runnable() {
@Override
public void run() {
popwindow.showAtLocation(mView, Gravity.CENTER, 0, 0);
}
});
总结: PopupWindow必须在某个事件中显示或者是开启一个新线程去调用,不能直接在onCreate方法中显示一个Popupwindow,否则永远会有以上的错误。
参考:popupwindow - Problems creating a Popup Window in Android Activity - Stack Overflow
2. Unable to add window --token null is not for an applicaiton
$BadTokenException: Unable to add window --
token null is not for an application
E/AndroidRuntime(1412): at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
......
该异常多见于AlertDialog组件的使用中抛出。
//抛异常代码
new AlertDialog.Builder(getApplicationContext()) //不能用getApplicationContext()
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Warnning")
.setPositiveButton("Yes", positiveListener)
.setNegativeButton( "No", negativeListener)
.create().show();
原因:导致报这个错是在于new AlertDialog.Builder(mcontext),虽然这里的参数是AlertDialog.Builder(Context context),但我们不能使用getApplicationContext()获得的Context,而必须使用Activity,因为只有一个Activity才能添加一个窗体。
解决方法:将new AlertDialog.Builder(Context context)中的参数用Activity.this(Activity 是你的 Activity 的名称)或者getActivity()来填充就可以正确的创建一个Dialog了
//修正后代码
new AlertDialog.Builder(this) //this可以替换为MainActivity.this或getActivity()
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Warnning")
.setPositiveButton("Yes", positiveListener)
.setNegativeButton( "No", negativeListener)
.create().show();
参考:java - Android custom dialog gives an error - Stack Overflow
3. Unable to add window --token android.os.BindeProxy@XXX is not valid; is your activity running
android.view.WindowManager$BadTokenException: Unable to add window --
token android.os.BinderProxy@4250d6d8 is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:698)
......
at dalvik.system.NativeStart.main(Native Method)
原因:从错误信息我们也可以明白其原因,此问题根本原因就是由于将要弹出的dialog所要依附的View已经不存在导致的。当界面销毁后再弹出来;或者界面跳转时我们的view发生改变,dialog依附的context发生变化或者界面未运行了。
解决方法:界面已经销毁引起的错误就只能判断界面是否存在然后再弹出了。
//修正后代码
if(!isFinishing()) {
alert.show();
}
参考:Unable to add window token android.os.BinderProxy@4250d6d8 is not valid; is your activity running? - Stack Overflow
4. Unable to add window --token android.app.LocalActivityManager$LocalActivityRecord @XXX is not vaild; is your activity running
android.view.WindowManager$BadTokenException: Unable to add window --
token android.app.LocalActivityManager$LocalActivityRecord@43e5b158
is not valid; is your activity running?
//异常代码
TipDialog dialog = new TipDialog(XXX.this) ;
原因:因为new对话框的时候,参数context 指定成了this,即指向当前子Activity的context。但子Activity是动态创建的,不能保证一直存在。其父Activity的context是稳定存在的,所以有下面的解决办法.
解决方法:将context替换为getParent()即可。 注意:要创建dialog对象,上下文环境必须是activity,同时若ActivityGroup中嵌套ActivityGroup,嵌套多少就该使用多少个getParent()。
//修正后代码,只有最多一个parent的情形
TipDialog dialog = new TipDialog(getParent()) ;
//修正后代码,适用于一个或多个parent的情形
Activity activity = TestActivity.this;
while (activity.getParent() != null) {
activity = activity.getParent();
}
TipDialog dialog = new TipDialog(activity) ;
5、当出现下面错误时候
08-21 03:43:16.679: E/AndroidRuntime(1087): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragment/com.example.fragment.MainActivity}: android.view.InflateException: Binary XML file line #5: Error inflating class fragment
肯定是那个MainActivity.xml文件出了问题,就在第五行,我用的fragment,里面的一个class="com.sss.TitleFragment" 原来是这个写错了,
那个包名写错了,改了就好,然后再xml里面写时候要注意是<fragment/>第一个是小写,不是大写,要记住
6、mTabWeixin.setOnClickListener((OnClickListener) this); 这样写会报错
08-21 04:06:16.920: E/AndroidRuntime(1274): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.fragment/com.example.fragment.MainActivity}: java.lang.ClassCastException: com.example.fragment.MainActivity cannot be cast to android.view.View$OnClickListener
后来改成mTabWeixin.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
stopService(intent);
}});就可以了
ation"
7、RecyclerView 在 ConstraintLayout 中超出边界
1️⃣ Constraint 约束不完整
在 ConstraintLayout 中,如果子控件没有被水平和垂直方向同时约束,
就会导致它的 wrap_content 尺寸无法正确计算,从而可能“超出”父布局范围
2️⃣ 使用 wrap_content 导致宽度不受控
RecyclerView 的内容是动态的,
wrap_content 在计算时可能会尝试“容纳所有子项”,
因此容易撑大,超出预期范围。
3️⃣ 外层 ConstraintLayout 使用 wrap_content
你外层的 ConstraintLayout :
android:layout_width="wrap_content" android:layout_height="wrap_content"
➡️ 这意味着父容器本身会根据子控件尺寸扩张,
当 RecyclerView 过宽时,父布局也会被“撑开”,造成视觉上“超出边界”。
8、Java调用kotlin扩展函数方法:
Kotlin扩展函数在编译后会转换为接收者作为第一个参数的静态方法
fun BaseVbFragment<*, *>.hideStatus() 变成 public static void hideStatus(BaseVbFragment<?, ?> receiver)
因此在Java中需要显式传递接收者对象作为第一个参数
1186

被折叠的 条评论
为什么被折叠?



