Android set View.GONE не «освобождает» пространство в просмотре списка - PullRequest
5 голосов
/ 27 октября 2011

У меня есть список с некоторыми пунктами, которые можно пометить как «готово».Также есть кнопка с надписью «скрыть готовые предметы».

Однако, когда я действительно скрываю элементы, устанавливая setVisibility (View.GONE), в списке остается свободное место.

Не должно быть так сложно переключать элементы списка в просмотре списка

Ответы [ 7 ]

9 голосов
/ 28 октября 2011

Изменение android: layout_height = "wrap_content" на android: layout_height = "fill_parent" исправило проблему .. тестировал с длинным списком .. с коротким списком то же пространство было над списком .. Глупая ошибка ..

Спасибо всем за помощь .. теперь все работает.

3 голосов
/ 27 октября 2011

Вы пытаетесь скрыть весь элемент списка? Если так, то я думаю, что представлению списка это не понравится, потому что оно все еще рассчитывается с тем же количеством элементов. Я не думаю, что это просто проигнорирует это, потому что это ушло.

Чистым решением было бы вернуть еще один getCount и просто игнорировать элементы, которые вы хотите скрыть. Или удалите элементы из внутреннего списка использованных. Вызовите notifyDataSetChanged на адаптере, когда вы изменили количество элементов в списке.

1 голос
/ 27 октября 2011

Вы также должны работать со списком адаптеров ...

0 голосов
/ 29 апреля 2019
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;
}
0 голосов
/ 15 ноября 2018

View.GONE фактически освобождает место, но другие элементы могли быть ограничены их текущими позициями. Попробуй это. В файле пользовательского макета (который служит видом для элементов списка),

Предположим, что если X - это элемент пользовательского интерфейса, которым вы хотите стать GONE, W - это элемент под X, а Y - это элемент над X

В пользовательской компоновке вашего ListView (при условии, что это относительная компоновка) Прикрепите верхнюю часть W к нижней части X. А затем прикрепите верхнюю часть элемента X к нижней части Y.

0 голосов
/ 01 ноября 2016

После проверки многих решений ни одно из которых не решило мою проблему с пустым пространством, поэтому я решил найти свое решение.

У меня было две основные проблемы: 1) У меня было пустое пространство из-завидимость, что я установил его видимость как пропавшую 2) У меня также был dividerHeight 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, к каждому не пропущенному элементу я добавил другой макет с параметром transродительский фон (цвет делителя в моем случае должен быть прозрачным) и добавлен нижний отступ 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>

возможно, это не элегантно, но это решение сработало для меня

0 голосов
/ 29 апреля 2014

Я смог решить эту проблему, используя решение Knickedi и комментарии под ним. Просто хотел показать мой относительно полный адаптер, чтобы немного его прояснить.

У меня есть класс StockItem с полями для хранения диапазона данных для одного элемента запаса. Для пользовательского ArrayAdapter конструктор берет полный список StockItems, извлеченных из таблицы базы данных, и любые методы добавления / удаления, которые я могу добавить в будущем, также будут работать с этим списком (mList). Однако я переопределил getView () и getCount () для чтения из второго списка (mFilteredList), созданного с использованием метода filterList ():

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();
    }
}

filterList (поиск строки) вызывается из OnQueryTextListener и удаляет элементы списка, описания которых не соответствуют введенному тексту.

В случае большого списка, filterList () может быть проблемой в главном потоке, но это не имеет значения для этого вопроса.

EDIT: метод getItem (position) также должен быть переопределен для возврата элемента из mFilteredList.

@Override
public StockItem getItem(int position) {

    return mFilteredList.get(position);
}
...