Android View.getWidth()=0

本文介绍了一种解决在View未完成绘制前获取其尺寸的问题的方法。通过使用Runnable和post方法,在UI线程完成后执行子线程,从而正确获取View的宽度和高度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发过程中,用到了一个自定义的View,而在View的内容数据没有被加载进来时,我想要先绘制这个View的背景,于是在使用到:

Rect bgRect = new Rect(report_ecg_wave.getLeft(), report_ecg_wave.getTop(), report_ecg_wave.getWidth(),
report_ecg_wave.getHeight());

report_ecg_wave.setBgRect(bgRect);
report_ecg_wave.initParams();
report_ecg_wave.drawBitmap();

时报错:java.lang.IllegalArgumentException: width and height must be > 0


后来了解到在onCreate()时获取view的width和height时,由于view还没有被绘制到界面上,此时获取不到view的width和height。晚上查看了一些其他童鞋的解决方案,有重写onWindowsFocuschanged的,也有其他的,感觉有些麻烦。所以就想到用另起线程执行的方式,这样可以在UI线程执行完成之后,才执行该子线程,此时就可以得到view的width以及height了,而且很简单的两行代码:

report_ecg_wave.post(new Runnable() {
@Override
public void run() {
drawWaveBg();
}
});

package com.lc.bailingbird.view; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import androidx.annotation.NonNull; import com.lc.bailingbird.R; import java.util.ArrayList; import java.util.List; /** * 底部滑动选择弹跳框 */ public class SlideDialog extends Dialog { private boolean isCancelable = false; private boolean isBackCancelable = false; private Context mContext; //上下文 private List<String> list = new ArrayList<>(0); //数据 private int selectPos; //默认选中位置 private OnSelectListener mSelectListener; //监听 public SlideDialog(@NonNull Context context, List<String> list, boolean isCancelable, boolean isBackCancelable) { super(context, R.style.SlideDialog); this.mContext = context; this.isCancelable = isCancelable; this.isBackCancelable = isBackCancelable; this.list = list; this.selectPos = 0; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置View setContentView(R.layout.dialog_picker); //设置点击物理返回键是否可关闭弹框 setCancelable(isCancelable); //设置点击弹框外是否可关闭弹框 setCanceledOnTouchOutside(isBackCancelable); //设置view显示位置 Window window = this.getWindow(); window.setGravity(Gravity.BOTTOM); WindowManager.LayoutParams params = window.getAttributes(); params.width = WindowManager.LayoutParams.MATCH_PARENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; window.setAttributes(params); //初始化控件 TextView tv_cancel = findViewById(R.id.btn_cancel); TextView tv_agree = findViewById(R.id.btn_sure); EasyPickerView pickerView = findViewById(R.id.pickerView); //取消点击事件 tv_cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //取消 mSelectListener.onCancel(); dismiss(); } }); //确认点击事件 tv_agree.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //确认 mSelectListener.onAgree(list.get(selectPos)); dismiss(); } }); //设置数据 pickerView.setDataList(list); //监听数据 pickerView.setOnScrollChangedListener(new EasyPickerView.OnScrollChangedListener() { @Override public void onScrollChanged(int curIndex) { //滚动选中项发生变化 } @Override public void onScrollFinished(int curIndex) { //滚动结束 selectPos = curIndex; } }); } public interface OnSelectListener { //取消 void onCancel(); //确认 void onAgree(String txt); } public void setOnSelectClickListener(OnSelectListener listener) { this.mSelectListener = listener; } } 需要在选择列表中间加灰色分割线
最新发布
07-08
<think>我们正在处理一个Android开发问题:在SlideDialog(可能是一个底部弹窗)中的EasyPickerView(选择器视图)添加灰色分割线(divider)。 根据用户描述,他想要在“选择列表中间”添加分割线,这意味着我们需要在列表项之间添加分割线。 参考提供的引用: 引用[1]和[2]展示了如何创建分割线的XML形状(shape)资源。我们可以创建一个高度为1px(或根据需求调整)的灰色矩形。 引用[3]展示了如何通过自定义RecyclerView.ItemDecoration来添加分割线。虽然EasyPickerView可能不是RecyclerView,但类似的思路可以应用。 但是,请注意用户提到的组件是EasyPickerView。由于EasyPickerView可能是一个自定义的选择器控件,我们需要确认其内部实现。 然而,在没有具体实现细节的情况下,我们可以假设EasyPickerView可能是基于ListView、RecyclerView自定义ViewGroup实现的。 通常,在Android中添加分割线的方法有: 1. 如果EasyPickerView是ListView或RecyclerView,我们可以使用系统提供的divider属性或自定义ItemDecoration。 2. 如果是自定义ViewGroup,则需要在绘制手动绘制分割线,或者使用一个包含分割线的item布局。 由于用户提到了SlideDialog和EasyPickerView,并且希望添加分割线,我们可以尝试以下方法: 方法一:通过设置EasyPickerView的divider属性(如果支持) 如果EasyPickerView继承自ListView或AbsListView,我们可以直接在布局文件中设置divider属性,例如: <EasyPickerView android:id="@+id/pickerView" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@drawable/divider_line" android:dividerHeight="1dp" ... /> 其中,@drawable/divider_line是一个自定义的drawable,例如一个灰色的线。 方法二:使用ItemDecoration(如果EasyPickerView内部是RecyclerView) 如果EasyPickerView内部使用了RecyclerView,我们可以通过添加ItemDecoration来实现。例如,创建一个类似引用[3]中的分割线类,然后添加到EasyPickerView内部的RecyclerView中。 方法三:在item布局中添加分割线 我们可以在每个item的布局底部(或顶部)添加一个View作为分割线,注意最后一个item可能不需要分割线。 考虑到用户希望添加在“中间”,即每个条目之间,方法一和方法二更为合适。 但是,由于我们不知道EasyPickerView的具体实现,而且用户要求的是在SlideDialog中的EasyPickerView,我们可能需要查看EasyPickerView的文档或源码。 如果EasyPickerView是一个第三方库,我们可以查看其文档是否支持设置分割线。如果没有,我们可以考虑以下步骤: 步骤: 1. 创建一个分割线的drawable资源文件,例如:divider_gray.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#CCCCCC" /> <!-- 灰色 --> <size android:height="1px" /> <!-- 高度为1像素 --> </shape> 2. 尝试在布局文件中为EasyPickerView设置divider属性(如果支持): android:divider="@drawable/divider_gray" android:dividerHeight="1px" 3. 如果EasyPickerView不支持divider属性,我们可以尝试通过反射或自定义的方式获取其内部的ListView/RecyclerView,然后设置分割线。 4. 如果以上都不可行,我们可能需要自定义一个分割线装饰(ItemDecoration)并添加到EasyPickerView内部的RecyclerView(如果有的话)。 由于用户的问题中提到了“EasyPickerView”,我假设这是一个特定的控件。根据常见的实现,很多选择器控件都是继承自ViewGroup并自己处理绘制,因此可能不支持直接设置divider。 因此,我建议先尝试方法一(设置divider属性)是否有效。如果无效,我们可以考虑方法三:修改item布局。 方法三的具体操作: 假设我们有一个item布局(例如:item_picker.xml),原本只有一个TextView,现在我们在TextView下面添加一个分割线: <TextView android:id="@+id/text_item" ... /> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@drawable/divider_gray" android:layout_below="@id/text_item" /> <!-- 如果是RelativeLayout,需要调整布局 --> 注意:这样每个item都会有一条分割线,包括最后一个。为了避免最后一个也有,我们可以在数据适配器中根据位置判断是否显示分割线(设置View的可见性)。 然而,方法三需要修改适配器的布局和逻辑,可能稍显麻烦。 另一种思路:如果EasyPickerView是继承自RecyclerView或ListView,我们可以通过代码设置分割线。 例如,如果EasyPickerView内部是RecyclerView,我们可以: DividerItemDecoration divider = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL); divider.setDrawable(ContextCompat.getDrawable(context, R.drawable.divider_gray)); easyPickerView.addItemDecoration(divider); 注意:EasyPickerView可能没有addItemDecoration方法,所以我们需要获取其内部的RecyclerView。 由于我们无法确定EasyPickerView的实现,这里提供两种可能的代码: 情况1:EasyPickerView本身是RecyclerView的子类(或者有方法获取其内部的RecyclerView) RecyclerView recyclerView = (RecyclerView) easyPickerView; // 如果EasyPickerView就是RecyclerView // 或者 RecyclerView recyclerView = easyPickerView.getRecyclerView(); // 如果EasyPickerView提供了这样的方法 然后添加ItemDecoration。 情况2:EasyPickerView是ListView的子类 ListView listView = (ListView) easyPickerView; listView.setDivider(getResources().getDrawable(R.drawable.divider_gray)); listView.setDividerHeight(1); // 高度为1像素,注意单位是像素,如果使用dp需要转换 总结:最佳实践是先查看EasyPickerView的文档或源码,确定其类型。如果无法确定,尝试设置divider属性。如果不行,尝试获取内部控件。再不行,修改item布局。 由于用户没有提供更多细节,我们给出一个通用的解决方案: 步骤: 1. 创建分割线drawable(divider_gray.xml) 2. 在布局文件中设置EasyPickerView的divider属性(如果支持) 3. 如果布局文件中设置无效,尝试在代码中设置: if (easyPickerView instanceof ListView) { ((ListView) easyPickerView).setDivider(getResources().getDrawable(R.drawable.divider_gray)); ((ListView) easyPickerView).setDividerHeight(1); // 注意:这里高度单位是像素,如果设计是dp,需要转换 } else if (easyPickerView instanceof RecyclerView) { DividerItemDecoration divider = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL); divider.setDrawable(ContextCompat.getDrawable(context, R.drawable.divider_gray)); ((RecyclerView) easyPickerView).addItemDecoration(divider); } else { // 如果既不是ListView也不是RecyclerView,考虑修改item布局 // 或者查看EasyPickerView的文档是否有设置分割线的方法 } 4. 如果EasyPickerView是一个自定义控件,并且没有提供设置分割线的方法,那么可能需要修改其源代码(如果是自己的项目)或者使用其他方法。 注意:在代码中设置divider,需要将高度转换为像素。例如,如果设计是1dp,则: int heightInPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()); 然后对于ListView:setDividerHeight(heightInPx); 对于RecyclerView,我们已经在drawable中定义了高度(1px),所以不需要额外设置高度。 最后,由于用户要求的是灰色分割线,我们已经在drawable中使用了灰色(#CCCCCC),可以根据需要调整颜色。 如果用户使用的是第三方库,建议查看该库的文档或源码,看是否有内置的分割线设置方法。 希望这些方法能帮助用户解决问题。 相关问题: 1. 如何在Android自定义ListView的分割线? 2. RecyclerView的ItemDecoration有哪些使用技巧? 3. 如何为Android弹窗中的列表控件添加分割线? 4. 如何获取自定义控件内部的子控件(如RecyclerView)? 5. 如何在代码中设置ListView的分割线高度(单位为dp)?</think>### 在 Android SlideDialog 的 EasyPickerView 中添加灰色分割线 要在 SlideDialog 的 EasyPickerView 中添加灰色分割线,可以通过以下两种方法实现: #### 方法一:XML 形状资源 + 布局属性(推荐) 1. **创建分割线形状** 在 `res/drawable/` 下新建 `divider_gray.xml`: ```xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#CCCCCC" /> <!-- 灰色 --> <size android:height="1dp" /> <!-- 分割线高度 --> </shape> ``` 2. **在布局文件中添加分割线** 在 EasyPickerView 的父布局中添加分割线 View: ```xml <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- 列表项1 --> <TextView ... /> <!-- 灰色分割线 --> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@drawable/divider_gray"/> <!-- 列表项2 --> <TextView ... /> </LinearLayout> ``` #### 方法二:自定义 ItemDecoration(适用于 RecyclerView) 如果 EasyPickerView 基于 RecyclerView 实现: ```java public class GrayDividerDecoration extends RecyclerView.ItemDecoration { private final Drawable divider; public GrayDividerDecoration(Context context) { divider = ContextCompat.getDrawable(context, R.drawable.divider_gray); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); for (int i = 0; i < parent.getChildCount() - 1; i++) { View child = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); int top = child.getBottom() + params.bottomMargin; int bottom = top + divider.getIntrinsicHeight(); divider.setBounds(left, top, right, bottom); divider.draw(c); } } } ``` **应用分割线**: ```java EasyPickerView pickerView = findViewById(R.id.pickerView); pickerView.addItemDecoration(new GrayDividerDecoration(this)); ``` #### 关键配置说明 1. **颜色调整**:修改 `#CCCCCC` 值可改变灰色深度(如 `#999999` 为深灰) 2. **高度调整**:修改 `<size android:height>` 或 `divider.getIntrinsicHeight()` 控制线粗 3. **位置控制**:通过调整 `RecyclerView.ItemDecoration` 的 `top`/`bottom` 计算逻辑可改变分割线位置[^3] > 提示:如果 EasyPickerView自定义组件,检查其是否支持 `android:divider` 属性,部分实现可直接在 XML 中配置[^1][^2] --- ### 相关问题 1. 如何在 Android 中动态改变分割线的颜色和粗细? 2. RecyclerView 的分割线如何实现首尾项不显示分割线? 3. 如何为不同列表项设置不同样式的分割线(如间隔线)? 4. SlideDialog 底部弹窗布局优化有哪些最佳实践? 5. 如何解决自定义分割线在滚动的性能问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值