ListView 不使用自定义视图更新大小

Posted

技术标签:

【中文标题】ListView 不使用自定义视图更新大小【英文标题】:ListView does not update size with custom view 【发布时间】:2019-05-25 05:56:23 【问题描述】:

我为我的ListView 创建了一个自定义视图我的自定义视图扩展了LinearLayout,它充当普通ListView 的可扩展项所以我现在遇到的错误真的很奇怪,所以我有我的@987654327 @属性设置为

<ListView
    android:id="@android:id/list"
    android:layout_
    android:layout_ />

所以高度是wrap_content 让我们记下这一点,因为这将有助于我们理解问题。

这是我的 ListVIew 外观的视频。第一个 Expandable 项目是可见的,但其他项目没有填满屏幕,我非常有信心这是因为 wrap_content 但只要我展开其中一个项目,它就会填满整个屏幕。我该如何解决这个问题?我的猜测是因为 ListView 没有更新其他项目?这是我的自定义视图代码

import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListAdapter;

import java.util.ArrayList;
import java.util.List;


public class ExpandableInnerListView extends LinearLayout 
    private ListAdapter adapter;
    private DataChangeObserver dataChangeObserver;
    private View mainView;
    private List<View> reusableViews = new ArrayList<>();
    private boolean viewsHidden = true;
    int mDividerHeight = 1;

    public ExpandableInnerListView(Context context) 
        this(context, null);
    

    public ExpandableInnerListView(Context context, AttributeSet attrs) 
        this(context, attrs, 0);
    

    public ExpandableInnerListView(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        setOrientation(VERTICAL);
    

    public void setAdapter(ListAdapter adapter) 
        if (this.adapter != null && dataChangeObserver != null) 
            this.adapter.unregisterDataSetObserver(dataChangeObserver);
        
        this.adapter = adapter;
    

    public void setMainView(View mainView) 
        this.mainView = mainView;
    

    public void toggle() 
        viewsHidden = !viewsHidden;
        dataChangeObserver.onInvalidated();
    

    @Override
    protected void onAttachedToWindow() 
        super.onAttachedToWindow();
        if (adapter != null) 
            dataChangeObserver = new DataChangeObserver();
            adapter.registerDataSetObserver(dataChangeObserver);
            setupView();
        
    

    @Override
    protected void onDetachedFromWindow() 
        super.onDetachedFromWindow();
        if (adapter != null && dataChangeObserver != null) 
            adapter.unregisterDataSetObserver(dataChangeObserver);
            dataChangeObserver = null;
        
    

    private void setupView() 
        this.removeAllViews();
        setupMainLayout();
        setupInnerView();

    

    public void setupMainLayout() 
        if (mainView == null) 
            throw new NullPointerException("Main View cannot be null!");
        
        addView(mainView);
    

    public void setupInnerView() 
        if (viewsHidden) return;
        int reusableCount = reusableViews.size();
        int count = adapter.getCount();
        for (int i = 0; i < count; i++) 
            View converView = null;
            if (i < reusableCount) 
                converView = reusableViews.get(i);
            
            View view = adapter.getView(i, converView, this);
            if (i >= reusableCount) 
                reusableViews.add(view);
            
            if(mDividerHeight > 0) 
                View divider = new View(getContext());
                divider.setBackground(new ColorDrawable(0xFFCCCCCC));
                LinearLayout.LayoutParams dividerLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mDividerHeight);
                divider.setLayoutParams(dividerLayoutParams);
                addView(divider);
            
            addView(view);
        
    

    private class DataChangeObserver extends DataSetObserver 
        @Override
        public void onChanged() 
            super.onChanged();
            setupView();
        

        @Override
        public void onInvalidated() 
            super.onInvalidated();
            setupView();
        
    

这是我的整个片段视图 XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:background="#ffffff">

    <include
        android:id="@+id/back_button_container"
        layout="@layout/kik_back_button" />

    <FrameLayout
        android:id="@+id/topbar"
        android:layout_
        android:layout_
        android:layout_alignParentTop="true"
        android:layout_toEndOf="@id/back_button_container"
        android:layout_toRightOf="@id/back_button_container" />

    <include
        android:id="@+id/nav_bar_shadow"
        layout="@layout/navbar_underline"
        android:layout_
        android:layout_
        android:layout_below="@id/topbar" />

    <EditText
        android:id="@android:id/edit"
        android:layout_
        android:layout_
        android:layout_below="@+id/topbar"
        android:layout_centerHorizontal="true"
        android:textSize="18sp"
        android:layout_marginEnd="15dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:drawablePadding="15dp"
        android:hint="Search Settings"
        android:inputType="textNoSuggestions"
        android:maxLines="1"
        android:paddingEnd="16dp"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:paddingStart="16dp"
        android:textStyle="normal"
        android:typeface="sans" />

    <ImageView
        android:id="@android:id/icon"
        android:layout_
        android:layout_
        android:layout_alignEnd="@android:id/edit"
        android:layout_alignRight="@android:id/edit"
        android:layout_alignTop="@android:id/edit"
        android:layout_marginEnd="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginTop="12dp"
        android:src="@drawable/delete_gray"
        android:visibility="gone" />

    <View
        android:id="@+id/top_divider"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@android:id/edit"
        android:layout_marginTop="15dp"
        android:background="@color/list_divider_color" />

    <ListView
        android:id="@android:id/list"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/top_divider"
        android:divider="@null"
        android:dividerHeight="0dp" />

    <View
        android:id="@+id/bottom_divider"
        android:layout_
        android:layout_below="@android:id/list"
        android:layout_
        android:background="@color/list_divider_color" />

    <TextView
        android:id="@android:id/text1"
        android:layout_
        android:layout_
        android:layout_centerInParent="true"
        android:text="No Settings Found"
        android:textSize="19.0sp"
        android:visibility="gone" />
</RelativeLayout>

如果有人能够发现错误发生的位置以及如何解决它,以及在某些情况下是否可能发生任何其他错误,那将是非常慷慨的。

【问题讨论】:

我很久以前就遇到过类似的问题。 ***.com/questions/34999997/…。但我会建议你使用可扩展的列表视图 @VivekMishra 我无法使用 Expandable ListView,适配器中有一些不可扩展的项目,例如复选框和摘要选项卡。 :) 我相信你可以使用一些布尔变量来控制你的复选框行为 @VivekMishra 正确使用可扩展的listview,当某些项目不应该扩展时,您必须通过隐藏视图或将内部列表大小设置为零来管理它。 我已经为 ListView 的工作可扩展项编写了代码,并且我的所有代码都适用于 ListView,如果我想切换,我将不得不花费大量时间重新编码。我只是等到有人发布答案来解决这个问题。 【参考方案1】:

看起来问题很小。我必须在设置 mainView 时重置视图

public void setMainView(View mainView) 
    this.mainView = mainView;
    setupView();

【讨论】:

【参考方案2】:

在更新新列表时尝试adapter.notifyDataSetChanged()

【讨论】:

我无法访问 CustomView 中的适配器。这没有帮助。

以上是关于ListView 不使用自定义视图更新大小的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 自定义视图:在 layoutSubviews() 中更新后忽略了固有内容大小

Android - 从自定义列表视图中删除一个项目并在长按时更新它

listview 项目未在自定义适配器的 getview 方法中显示分配的值

使用微调器从自定义列表视图中删除了错误的行

Android listview 不能用 android 中的 getFilter() 更新

Android自定义适配器和asyncTask不更新listView