GridView с динамическим числом TextViews - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь создать GridView с динамическим числом TextView s для каждого элемента.

Вот макет того, что я собираюсь сделать:

|-----------------|
|  Text  |  Text  |
|        |  Text  |
|-----------------|
|  Text  |  Text  |
|  Text  |        |
|  Text  |        |
|-----------------|
|  Text  |  Text  |
|  Text  |  Text  |
|-----------------|

Обратите внимание, что каждый элемент GridView имеет динамическое число, если TextView s, в зависимости от данных, возвращаемых из моего API.

У меня вопрос, как изменить приведенный ниже код, чтобы увеличить значение TextView длякаждый текст, который я хочу добавить в элемент GridView?

Вот код, который я использую для вызова адаптера (удален нерелевантный код):

private GridView gridView;

// Create a map to hold the text for each GridView item
// The Integer is simply the section number
private List<Map<Integer, List<String>>> items = new ArrayList<>();

// Get the GridView view
gridView = findViewById(R.id.grid_view);

// Add sample items to the list
Map<Integer, List<String>> map = new HashMap<>();
map.put(1, Collections.singletonList("Item 1"));

Map<Integer, List<String>> map2 = new HashMap<>();
map2.put(2, Arrays.asList("Item 1", "Item 2"));

Map<Integer, List<String>> map3 = new HashMap<>();
map3.put(3, Arrays.asList("Item 1", "Item 2", "Item 3"));

Map<Integer, List<String>> map4 = new HashMap<>();
map4.put(4, Collections.singletonList("Item 1"));

// Add the items to the list
items.add(map);
items.add(map2);
items.add(map3);
items.add(map4);

// Initialize the adapter
GridViewAdapter gridViewAdapter = new GridViewAdapter(getContext(), items);
gridView.setAdapter(gridViewAdapter);

Вот мой GridViewадаптер:

public class GridViewAdapter extends BaseAdapter {

    private final Context mContext;
    private final List<Map<Integer, List<String>>> items;
    private LayoutInflater layoutInflater;

    public GridViewAdapter(Context context, List<Map<Integer, List<String>>> items) {
        this.mContext = context;
        this.items = items;
        layoutInflater = LayoutInflater.from(mContext);
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        Map<Integer, List<String>> item = items.get(position);

        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.gridview_item, parent, false);

            viewHolder = new ViewHolder();

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        for (Map.Entry<Integer, List<String>> entry : item.entrySet()) {
            Integer key = entry.getKey();
            List<String> values = entry.getValue();

            // For each value, inflate a TextView layout...
            for (String value : values) {
                // What goes here?
                // How do I inflate the TextView layout (shown below) for each value and add it to the parent view?
            }
        }

        return convertView;
    }

    static class ViewHolder {
        // What goes here?
    }

}

Вот мой gridview_item макет:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

И, наконец, вот мой gridview_textview макет, который я хочу надуть и добавить к приведенному выше макету:

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

Как мне этого добиться и как будет выглядеть код?

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018
// For each value, inflate a TextView layout...
for (String value : values) {
    // What goes here?
    // How do I inflate the TextView layout (shown below) for each value and add it to the parent view?
}

Поскольку вы перерабатываете представления, вы должны убедиться в правильности нескольких вещей:

  • У вас есть достаточно просмотровчтобы показать все ваши строки
  • У вас нет слишком много просмотров для количества строк в этой ячейке

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

Итак, нам нужно убедиться, что у нас достаточно представлений для ваших строк.Давайте сделаем это сначала:

LinearLayout linear = (LinearLayout) convertView;

while (linear.getChildCount() < values.size()) {
    inflater.inflate(R.layout.gridview_textview, linear);
}

Теперь давайте заполним каждое TextView:

for (int i = 0; i < values.size(); ++i) {
    String text = values.get(i);
    TextView textView = (TextView) linear.getChildAt(i);
    textView.setText(text);
    textView.setVisibility(View.VISIBLE);
}

И давайте скроем все дополнительные представления:

for (int i = values.size(); i < linear.getChildCount(); ++i) {
    View v = linear.getChildAt(i);
    v.setVisibility(View.GONE);
}

Весь код вместе:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = layoutInflater.inflate(R.layout.gridview_item, parent, false);
    }

    LinearLayout linear = (LinearLayout) convertView;

    Map<Integer, List<String>> item = items.get(position);

    for (Map.Entry<Integer, List<String>> entry : item.entrySet()) {
        Integer key = entry.getKey();
        List<String> values = entry.getValue();

        for (String value : values) {
            while (linear.getChildCount() < values.size()) {
                inflater.inflate(R.layout.gridview_textview, linear);
            }

            for (int i = 0; i < values.size(); ++i) {
                String text = values.get(i);
                TextView textView = (TextView) linear.getChildAt(i);
                textView.setText(text);
                textView.setVisibility(View.VISIBLE);
            }

            for (int i = values.size(); i < linear.getChildCount(); ++i) {
                View v = linear.getChildAt(i);
                v.setVisibility(View.GONE);
            }
        }
    }

    return convertView;
}
0 голосов
/ 20 декабря 2018

Я бы порекомендовал использовать RecyclerView с GridLayoutManager вместо GridView.

. В любом случае вы хотите, чтобы ваш ViewHolder делал следующее (мне сложно сделать макет кода)так что я просто напишу шаги:

  • Ваш ViewHolder будет раздувать макет gridview_item и получит ссылку на LinearLayout.
  • У вас будет метод наваш видоискатель, такой как bindStrings(List<String> strings), который будет раздувать текстовое представление для каждого из них.

Вот как будет выглядеть код:

public void bindStrings(List<String> strings) {
   Context context = myItemView.getContext();
   LinearLayout parentLayout = (LinearLayout) myItemView;

   for(String item : strings) {
      TextView textView = TextView(context);
      textView.setText(item);
      parentLayout.addView(textView);
   }
}
...