【问题标题】:Android set View.GONE does not "release" space in listviewAndroid set View.GONE 不会在列表视图中“释放”空间
【发布时间】:2011-12-16 13:15:58
【问题描述】:

我有一个列表视图,其中包含一些可以标记为“完成”的项目。还有一个切换按钮,上面写着“隐藏已完成的项目”。

但是,当我通过设置 setVisibility(View.GONE) 隐藏项目时,列表中仍有空间..

在列表视图中切换列表项应该不是那么难吗?

【问题讨论】:

    标签: android listview layout visibility


    【解决方案1】:

    将 android:layout_height="wrap_content" 更改为 android:layout_height="fill_parent" 解决了这个问题.. 正在测试一个长列表.. 一个短列表相同的空间在列表上方.. 愚蠢的错误..

    感谢大家的帮助.. 现在一切正常。

    【讨论】:

      【解决方案2】:

      您是否要隐藏整个列表项?如果是这样,我猜列表视图不会喜欢这样,因为它仍在使用相同数量的项目进行计算。我不认为它会因为它消失而忽略它。

      干净的解决方案是返回另一个 getCount 并忽略您要隐藏的项目。或从内部使用列表中删除项目。当您修改列表中的项目数量时,请在适配器上调用notifyDataSetChanged

      【讨论】:

      • 所以保留一个单独的列表,其中包含所有且仅选中的项目,并使用显示正确信息所需的任何列表。听起来像一个计划。
      • 根本不起作用。我根据按钮的切换状态返回正确的项目和正确的计数。列表中的项目是正确的项目,但仍然存在很大的空白。难道持有者类还在吗?
      • notifyDataSetChanged 将触发列表使用返回的getCount 值对所有项目调用getView。这应该可以解决问题。但我不能帮你,因为我不知道任何细节。好像真的有什么不对劲的地方……
      • 那部分工作正常,列表的高度没有“刷新”,仍然在列表上方保留空间。真奇怪。
      【解决方案3】:

      您也应该对列表适配器进行操作...

      【讨论】:

      • 这一切都在列表适配器上。
      【解决方案4】:

      我能够使用 Knickedi 的解决方案及其下的 cmets 解决这个问题。只是想展示一下我比较完整的适配器来澄清一下。

      我有一个 StockItem 类,其中包含用于保存单个库存项目的一系列数据的字段。对于自定义的 ArrayAdapter,构造函数获取从数据库表中检索到的 StockItems 的完整列表,并且我将来可能添加的任何添加/删除方法也将在此列表 (mList) 上进行操作。但是,我覆盖了 getView() 和 getCount() 以从使用 filterList() 方法生成的第二个列表 (mFilteredList) 中读取:

      public class StockItemAdapter extends ArrayAdapter<StockItem> {
      
          ...
          ArrayList<StockItem> mList;
          ArrayList<StockItem> mFilteredList;
      
          public StockItemAdapter(Context context, int resource, ArrayList<StockItem> list) {
                  super(context, resource, list);
      
          ...
              mList = list;
              mFilteredList = list;
          }
      
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
      
              View row = convertView;
              StockItemHolder holder = null;
      
              if (row == null) {
                  LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
                  row = inflater.inflate(mResource, parent, false);
      
                  holder = new StockItemHolder();
                  holder.imageView = (ImageView)row.findViewById(R.id.imageView);
                  ...
                  row.setTag(holder);
              } else {
                  holder = (StockItemHolder)row.getTag();
              }
              StockItem stockItem = mFilteredList.get(position);
              if (stockItem.getImage() != null) {
                  holder.imageView.setImageBitmap(stockItem.getImage());
              } else {
                  holder.imageView.setImageResource(R.drawable.terencephilip);
              }
              ...
              return row;
          }
      
          @Override
          public int getCount() {
              return mFilteredList.size();
          }
      
          static class StockItemHolder {
      
              ImageView imageView;
              ...
          }
      
          public void filterList(String search) {
      
              mFilteredList = new ArrayList<StockItem>();
              for (StockItem item : mList) {
                  if (item.getDescription().toLowerCase(Locale.ENGLISH)
                          .contains(search.toLowerCase(Locale.ENGLISH))) {
                      mFilteredList.add(item);
                  }
              }
              notifyDataSetChanged();
          }
      }
      

      从 OnQueryTextListener 调用 filterList(String search) 并删除描述与输入文本不匹配的列表项。

      在列表很大的情况下,filterList()可能是主线程的问题,但这与这个问题无关。

      编辑:还必须重写 getItem(position) 方法才能从 mFilteredList 返回项目。

      @Override
      public StockItem getItem(int position) {
      
          return mFilteredList.get(position);
      }
      

      【讨论】:

        【解决方案5】:

        在检查了许多解决方案后,都没有解决我的空白问题,所以我决定提出我的解决方案。

        我有两个主要问题: 1)我有一个空白空间,因为我将其可见性设置为消失了 2)我也有 12dp 的分隔高度,即使我解决了第一个问题,我仍然有列表视图的固定分隔高度

        解决方案:

        1.1) 我在列表的数据中添加了一个布尔值,以通知适配器跳过了哪些项目

        1.2) 我创建了一个空布局来模拟“跳过的项目”

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="0dp"
            android:layout_height="0dp"/>
        

        1.3) 我的列表视图中有几种类型的视图,选中的项目,常规项目和现在跳过的项目

            public class AdvancedTestAdapter extends BaseAdapter
        {
        
            private static final int        REGULAR_STEP    = 0;
            private static final int        SELECTED_STEP   = 1;
            private static final int        SKIPPED_STEP    = 2;
        
            private static final int        TYPE_MAX_COUNT  = 3;
        
        
            private List<AdvancedTestData>  _data;
            private Context                 _context;
            private Typeface                _fontTypeFace;
        
            public AdvancedTestAdapter(Context context, List<AdvancedTestData> data)
            {
                _context = context;
                _data = data;
                _fontTypeFace = Typeface.createFromAsset(_context.getResources().getAssets(), Consts.Fonts.UniversLTStdBoldCn);
            }
        
            @Override
            public AdvancedTestData getItem(int position)
            {
                return _data.get(position);
            }
        
            @Override
            public int getCount()
            {
                return _data.size();
            }
        
            @Override
            public long getItemId(int position)
            {
                return 0;
            }
        
            @Override
            public int getItemViewType(int position)
            {
                AdvancedTestData step = getItem(position);
                if(step.isSkipped())
                {
                    return SKIPPED_STEP;
                }
                return _data.get(position).isStepSelected() ? SELECTED_STEP : REGULAR_STEP;
            }
        
            @Override
            public int getViewTypeCount()
            {
                return TYPE_MAX_COUNT;
            }
        
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                RegularViewHolder regHolder;
                SelectedViewHolder selectHolder;
        
                AdvancedTestData item = getItem(position);
                int currentStepType = getItemViewType(position);
        
                switch (currentStepType)
                {
                    case SKIPPED_STEP:
                        convertView = LayoutInflater.from(_context).inflate(R.layout.skipped_item_layout, parent, false);
                        break;
                    case REGULAR_STEP:
                        if (convertView == null)
                        {
                            regHolder = new RegularViewHolder();
                            convertView = LayoutInflater.from(_context).inflate(R.layout.advanced_test_layout, parent, false);
                            regHolder._regTestUpperHeader = (TextView) convertView.findViewById(R.id.advanced_test_upper_name);
                            regHolder._regTestLowerHeader = (TextView) convertView.findViewById(R.id.advanced_test_lower_name);
                            regHolder._regTestImage = (ImageView) convertView.findViewById(R.id.advanced_test_image);
                            regHolder._regTestWithoutLowerHeader = (TextView) convertView.findViewById(R.id.step_without_lower_header);
        
                            regHolder._regTestUpperHeader.setTypeface(_fontTypeFace);
                            regHolder._regTestLowerHeader.setTypeface(_fontTypeFace);
                            regHolder._regTestWithoutLowerHeader.setTypeface(_fontTypeFace);
        
                            convertView.setTag(regHolder);
                        }
                        else
                        {
                            regHolder = (RegularViewHolder) convertView.getTag();
                        }
        
                        String upperHeader = item.getTestUpperHeader();
                        String lowerHeader = item.getTestLowerHeader();
        
                        if(lowerHeader.isEmpty())
                        {
                            regHolder._regTestUpperHeader.setVisibility(View.GONE);
                            regHolder._regTestLowerHeader.setVisibility(View.GONE);
                            regHolder._regTestWithoutLowerHeader.setVisibility(View.VISIBLE);
                            regHolder._regTestWithoutLowerHeader.setText(upperHeader);
                        }
                        else
                        {
                            regHolder._regTestUpperHeader.setVisibility(View.VISIBLE);
                            regHolder._regTestLowerHeader.setVisibility(View.VISIBLE);
                            regHolder._regTestWithoutLowerHeader.setVisibility(View.GONE);
        
                            regHolder._regTestUpperHeader.setText(upperHeader);
                            regHolder._regTestLowerHeader.setText(lowerHeader);
                        }
        
                        regHolder._regTestImage.setBackgroundResource(item.getResourceId());
                        break;
        
                    case SELECTED_STEP:
        
                        if (convertView == null)
                        {
                            selectHolder = new SelectedViewHolder();
                            convertView = LayoutInflater.from(_context).inflate(R.layout.advanced_selected_step_layout, parent, false);
        
                            selectHolder._selectedTestName = (TextView) convertView.findViewById(R.id.selected_header_text);
                            selectHolder._selectedTestDesc = (TextView) convertView.findViewById(R.id.selected_desc_text);
                            selectHolder._selectedPreFinishControllers = (RelativeLayout) convertView.findViewById(R.id.prefinish_step_controllers);
                            selectHolder._selectedFvEndControllers = (RelativeLayout) convertView.findViewById(R.id.advanced_fv_controllers);
                            selectHolder._selectedNvEndControllers = (RelativeLayout) convertView.findViewById(R.id.advanced_nv_controllers);
        
                            convertView.setTag(selectHolder);
                        }
                        else
                        {
                            selectHolder = (SelectedViewHolder) convertView.getTag();
                        }
        
                        selectHolder._selectedPreFinishControllers.setVisibility(View.INVISIBLE);
                        selectHolder._selectedFvEndControllers.setVisibility(View.INVISIBLE);
                        selectHolder._selectedNvEndControllers.setVisibility(View.INVISIBLE);
        
        
                        int testIndex = item.getTestIndex();
                        ADVANCED_QUICK_TEST_TESPS currentStep = ADVANCED_QUICK_TEST_TESPS.valueOf(testIndex);
        
                        //show action buttons in each step in advanced mode
                        switch (currentStep)
                        {
                            case QUESTIONS://nothing to show
                                break;
                            case RIGHT_VERIFICATION:
                            case LEFT_VERIFICATION:
                            case BINOCULAR_BALANCE:
                            case SPHERE_VERIFICATION:
                            case ADD_VERIFICATION:
                                if(item.isStepPreFinished())
                                {
                                    selectHolder._selectedPreFinishControllers.setVisibility(View.VISIBLE);
                                }
        
                                break;
        
                            case RIGHT_VA:
                            case LEFT_VA:
                            case BINO_VA:
                                selectHolder._selectedPreFinishControllers.setVisibility(View.VISIBLE);
                                break;
                            case FV_DONE:
                                selectHolder._selectedFvEndControllers.setVisibility(View.VISIBLE);
                                break;
                            case FULL_EXAM_DONE:
                                selectHolder._selectedNvEndControllers.setVisibility(View.VISIBLE);
                                break;
                        }
        
                        String textHeader = String.format("%s\n%s", item.getTestUpperHeader(),item.getTestLowerHeader());
                        selectHolder._selectedTestName.setText(textHeader);
                        selectHolder._selectedTestDesc.setText(item.getTestDescription());
        
                        break;
                }
        
                return convertView;
            }
        
            public void setData(List<AdvancedTestData> data)
            {
                _data = data;
                notifyDataSetChanged();
            }
        
            public static class RegularViewHolder
            {
                public TextView     _regTestWithoutLowerHeader;
                public TextView     _regTestUpperHeader;
                public TextView     _regTestLowerHeader;
                public ImageView    _regTestImage;
            }
        
            public static class SelectedViewHolder
            {
                public TextView         _selectedTestName;
                public TextView         _selectedTestDesc;
                public RelativeLayout   _selectedPreFinishControllers;
                public RelativeLayout   _selectedFvEndControllers;
                public RelativeLayout   _selectedNvEndControllers;
            }
        

        只有当项目被跳过时,适配器才会膨胀为空布局,如上一步所示,我仍然遇到分隔线高度问题

        2) 为了修复分隔线高度,我将分隔线高度改为 0 而不是 12dp, 每个未跳过的项目我添加了另一个具有透明背景的布局(在我的情况下,divier 颜色应该是透明的)并添加了 12dp 的底部填充

        例如我的一件物品

            <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent"
            android:orientation="vertical"
            android:paddingBottom="12dp" >
        
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/quick_test_background_selector" >
        
                <ImageView
                    android:id="@+id/advanced_test_image"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/done_step" />
        
                <TextView
                    android:id="@+id/advanced_test_upper_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="5dp"
                    android:layout_toRightOf="@id/advanced_test_image"
                    android:gravity="center_vertical"
                    android:text="ETAPE 1"
                    android:textColor="@android:color/black"
                    android:textSize="14sp"
                    android:textStyle="bold" />
        
                <TextView
                    android:id="@+id/advanced_test_lower_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignBottom="@id/advanced_test_image"
                    android:layout_marginLeft="5dp"
                    android:layout_toRightOf="@id/advanced_test_image"
                    android:gravity="center_vertical"
                    android:text="ETAPE 1"
                    android:textColor="@android:color/black"
                    android:textSize="14sp"
                    android:textStyle="bold" />
        
                <TextView
                    android:id="@+id/step_without_lower_header"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_alignBottom="@id/advanced_test_image"
                    android:layout_alignTop="@id/advanced_test_image"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="5dp"
                    android:layout_toRightOf="@id/advanced_test_image"
                    android:gravity="center_vertical"
                    android:text="123"
                    android:textColor="@android:color/black"
                    android:textSize="14sp"
                    android:textStyle="bold" />
            </RelativeLayout>
        
        </RelativeLayout>
        

        也许它并不优雅,但这个解决方案对我有用

        【讨论】:

          【解决方案6】:

          View.GONE 实际上是在释放空间,但其他元素可能已被限制在其当前位置。尝试这个。在自定义布局文件(作为列表项的视图)中,

          假设如果 X 是您想要 GONE 的 UI 元素,W 是 X 下方的元素,Y 是 X 上方的元素

          在你的ListView的自定义Layout中,(假设是相对布局)将W的顶部附加到X的底部。然后将元素X的顶部附加到Y的底部。

          【讨论】:

            【解决方案7】:
            convertView = inflater.inflate(R.layout.custom_layout, parent, false);
            
            if (CONDITION) {
                holder.wholeLayout.getLayoutParams().height = 1; // visibility Gone not working && 0 height crash app.
            } else {
                holder.wholeLayout.getLayoutParams().height = RelativeLayout.LayoutParams.WRAP_CONTENT;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-01-30
              • 2021-05-26
              • 2019-07-26
              • 2012-07-18
              • 2021-08-09
              • 1970-01-01
              • 2016-08-31
              • 1970-01-01
              相关资源
              最近更新 更多