Android 动态调整ListView行的大小
概述: 我有一个不同类型行的列表视图,包括不同高度的图像和文本。在运行时,我尝试根据行的宽度动态设置包含图像的布局的高度。因此,行的宽度设置为匹配父行,因为我们希望它填充设备的宽度,但必须在运行时计算高度,以获得帧的特定纵横比 下面是我正在使用的适配器的代码片段:Android 动态调整ListView行的大小,android,android-layout,listview,resize,android-adapter,Android,Android Layout,Listview,Resize,Android Adapter,概述: 我有一个不同类型行的列表视图,包括不同高度的图像和文本。在运行时,我尝试根据行的宽度动态设置包含图像的布局的高度。因此,行的宽度设置为匹配父行,因为我们希望它填充设备的宽度,但必须在运行时计算高度,以获得帧的特定纵横比 下面是我正在使用的适配器的代码片段: @Override public View getView(View convertView) { if (convertView == null) { convertView = LayoutInflater
@Override
public View getView(View convertView) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.chat_row_image, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ViewTreeObserver observer = holder.videoFrame.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
frameWidth = holder.container.getWidth();
int width = frameWidth;
int height = (int) (frameWidth / Utilities.MEDIA_CELL_ASPECT_RATIO);
Log.d(TAG, "Calculated : " + width + "," + height);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
holder.messageImage.setLayoutParams(params);
holder.videoFrame.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
Log.d(TAG, "Imageview : " + holder.messageImage.getWidth() + "," + holder.messageImage.getHeight());
}
});
return convertView;
}
问题是:这段代码运行得很好,但是在滚动列表视图的过程中,有一些很容易注意到的UI故障。主要的UI错误是,行与XML文件之间有一个预定义的高度,并且在图像加载完成后立即转换到我们计算的新高度。这会导致该行出现在屏幕上时,该行下方的全部内容突然移动。此外,我们正在从下到上滚动这是一个聊天线程
我尝试过的事情:
我们尝试从ListView通过setSelection方法滚动整个ListView,以便在用户看到内容之前预加载内容。这不起作用,而且在我们滚动图像的短暂时间内,图像似乎没有加载
我们尝试设置静态XML文件的宽度和高度,这解决了这个问题,但没有考虑不同的屏幕大小
我需要帮助的是:我们希望在动态调整布局大小的同时保持滚动平滑。最后一种方法是为每个屏幕大小类别创建不同的XML文件,并对高度进行硬编码,但这并不能使框架的纵横比保持在我们所希望的水平
请让我知道,如果有任何澄清,你会想要。提前谢谢 您可以在chat\u row\u image.xml中添加一个LinearLayout outside,如下所示
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/layout_ll
android:layout_width="wrap_content"
android:layout_height="wrap_content">
[...]
</LinearLayout>
</RelativeLayout>
您可以在chat\u row\u image.xml中添加一个LinearLayout outside,如下所示
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/layout_ll
android:layout_width="wrap_content"
android:layout_height="wrap_content">
[...]
</LinearLayout>
</RelativeLayout>
答案是在适配器的构造函数中设置框架的维度,而不是getView方法。根据Nannuo Lei的建议,我们没有使用ViewTreeObserver.OnGlobalLayoutListener,而是根据其他布局元素的显示宽度和填充/边距计算框架的尺寸
public ImageChatRow(Context context) {
this.mContext = context;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x - 40; //padding is 40 in our case
displayHeight = (int) (displayWidth / Utilities.MEDIA_CELL_ASPECT_RATIO);
}
然后在getView方法中,我们只是在膨胀视图之后直接设置帧的尺寸
public View getView(View convertView) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.chat_row, null);
holder = new ViewHolder(convertView);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(displayWidth, displayHeight);
layoutParams.gravity = Gravity.CENTER;
holder.frame.setLayoutParams(layoutParams);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
这解决了加载行和动态设置行高度时出现的问题。自从实现这段代码以来,我们没有在ScrollView中观察到任何跳跃 答案是在适配器的构造函数中设置框架的维度,而不是getView方法。根据Nannuo Lei的建议,我们没有使用ViewTreeObserver.OnGlobalLayoutListener,而是根据其他布局元素的显示宽度和填充/边距计算框架的尺寸
public ImageChatRow(Context context) {
this.mContext = context;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x - 40; //padding is 40 in our case
displayHeight = (int) (displayWidth / Utilities.MEDIA_CELL_ASPECT_RATIO);
}
然后在getView方法中,我们只是在膨胀视图之后直接设置帧的尺寸
public View getView(View convertView) {
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.chat_row, null);
holder = new ViewHolder(convertView);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(displayWidth, displayHeight);
layoutParams.gravity = Gravity.CENTER;
holder.frame.setLayoutParams(layoutParams);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
这解决了加载行和动态设置行高度时出现的问题。自从实现这段代码以来,我们没有在ScrollView中观察到任何跳跃 看起来您可以直接设置布局参数,而无需全局布局侦听器,并调用convertView.RequestLayoutHanks!这当然启发了我一个想法,即不使用全局布局侦听器,并在膨胀视图后立即设置值。我将在下面的回答中对此进行详细说明。看起来您可以直接设置布局参数,而无需全局布局侦听器,并调用convertView.RequestLayoutHanks!这当然启发了我一个想法,即不使用全局布局侦听器,并在膨胀视图后立即设置值。我将在下面的回答中对此进行详细说明