ListView, содержащий TabHost с другими ListViews

Я хочу создать ListView с последней строкой, показывающей TabHost с двумя вкладками. Я хотел бы загрузить еще ListView для каждой вкладки. Для этого я создал три файла XML.

В main.xml я загружаю исходный список. В файле mainlistdata.xml представлена ​​каждая строка списка. И последний xml — это tabslayout.xml. Этот макет используется для последней строки в основном списке. Он загрузит вкладку. Вот код со всем xml:

Мой основной класс таков:

public class MainActivity extends Activity {
    ArrayList<testData> myData = new ArrayList<testData>();
    ListView listContent;
    TestAdapter dataAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String[] aString = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };

        for (int i = 0; i < aString.length; i++) {
            myData.add(new testData(i, aString[i]));
        }

        listContent = (ListView) findViewById(R.id.mainlist);
        dataAdapter = new TestAdapter(this, myData,1);
        listContent.setAdapter(dataAdapter);
    }
}

И это класс, который загружает содержимое в списки и где я устанавливаю tabhost:

public class TestAdapter extends ArrayAdapter<testData> {
    private Context context;
    private ArrayList<testData> data;
    private ListView listContent,listContent2;
    public TabHost tabs;
    TestAdapter dataAdapter;
    private int choice;
    public TestAdapter(Context context, ArrayList<testData> data, int choice) {
        super(context, R.layout.mainlistdata, data);
        this.context = context;
        this.data = data;
        this.choice = choice;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView;
        if (choice == 1) {
            if (position == data.size()-1) {
                rowView = inflater.inflate(R.layout.tabslayout, parent, false);

                TextView first = (TextView) rowView.findViewById(R.id.dataTitle);
                TextView second = (TextView) rowView.findViewById(R.id.dataValue);
                TextView third = (TextView) rowView.findViewById(R.id.dataValueString);

                first.setText("Item " + data.get(position).getIntValue());
                second.setText(String.valueOf(data.get(position).getIntValue()));
                third.setText(data.get(position).getStringValue());

                tabs = (TabHost) rowView.findViewById(android.R.id.tabhost);
                tabs.setup();
                TabSpec tab1 = tabs.newTabSpec("Tab 1");
                TabSpec tab2 = tabs.newTabSpec("Tab 2");
                tab1.setContent(R.id.tabOne);
                tab2.setContent(R.id.tabTwo);
                tab1.setIndicator("One");
                tab2.setIndicator("two");
                tabs.addTab(tab1);
                tabs.addTab(tab2);
                tabs.setup();

                listContent = (ListView) rowView.findViewById(R.id.listOne);
                dataAdapter = new TestAdapter(context, data,2);
                listContent.setAdapter(dataAdapter);

                listContent2 = (ListView) rowView.findViewById(R.id.listTwo);
                dataAdapter = new TestAdapter(context, data,3);
                listContent2.setAdapter(dataAdapter);
            } else {
                rowView = inflater.inflate(R.layout.mainlistdata, parent, false);
                TextView first = (TextView) rowView.findViewById(R.id.dataTitle);
                TextView second = (TextView) rowView.findViewById(R.id.dataValue);
                TextView third = (TextView) rowView.findViewById(R.id.dataValueString);

                first.setText("Item " + data.get(position).getIntValue());
                second.setText(String.valueOf(data.get(position).getIntValue()));
                third.setText(data.get(position).getStringValue());
            }
        } else if (choice == 2) {
            rowView = inflater.inflate(R.layout.mainlistdata, parent, false);
            TextView first = (TextView) rowView.findViewById(R.id.dataTitle);
            TextView second = (TextView) rowView.findViewById(R.id.dataValue);
            TextView third = (TextView) rowView.findViewById(R.id.dataValueString);

            first.setText("Item tab1 " + data.get(position).getIntValue());
            second.setText(String.valueOf(data.get(position).getIntValue()));
            third.setText(data.get(position).getStringValue());
        } else {
            rowView = inflater.inflate(R.layout.mainlistdata, parent, false);
            TextView first = (TextView) rowView.findViewById(R.id.dataTitle);
            TextView second = (TextView) rowView.findViewById(R.id.dataValue);
            TextView third = (TextView) rowView.findViewById(R.id.dataValueString);

            first.setText("Item tab2 " + data.get(position).getIntValue());
            second.setText(String.valueOf(data.get(position).getIntValue()));
            third.setText(data.get(position).getStringValue());
        }
        return rowView;
    }
}

Как вы можете видеть на следующем изображении, я загружаю данные, а затем загружаю вкладки. Проблема в том, что каждая вкладка загружает только первую строку данных. Любая идея Как я могу это решить? введите здесь описание изображениявведите здесь описание изображения


person Favolas    schedule 24.04.2013    source источник
comment
Похоже, ваш подсчет неверен, какие данные вы указали для адаптера?   -  person shem    schedule 25.04.2013
comment
Привет, шем. Смотрите в основном классе. Данные представляют собой целое число и букву. Изображения показывают только последнюю часть списков. Основной список показывает, что ожидается, целые числа от 0 до 25 и буквы от a до z. Вкладка загружается правильно, но список на каждой из вкладок показывает только первый элемент данных.   -  person Favolas    schedule 25.04.2013
comment
когда choice стало 2 (или не 1)?   -  person shem    schedule 25.04.2013
comment
См. класс testadapter. Это для загрузки списка на вкладке один и два   -  person Favolas    schedule 25.04.2013
comment
да, конечно, это не сработает: у вас будет два скролла внутри друг друга. Я советую вам использовать эти кнопки (вместо tabhost), чтобы загружать больше элементов в одном и том же списке.   -  person Sherif elKhatib    schedule 28.04.2013
comment
@SherifelKhatib Привет. Спасибо за Ваш ответ. Что вы имеете в виду под советом использовать эти кнопки, что это за кнопки?   -  person Favolas    schedule 29.04.2013
comment
@Favolas Я имел в виду (используйте кнопки вместо хоста вкладок, чтобы загружать больше элементов в одном и том же списке)   -  person Sherif elKhatib    schedule 29.04.2013


Ответы (1)


Как уже сказал Шериф эль-Хатиб в своем комментарии, следует избегать наличия ListView в другом ListView. Решением ваших проблем является использование одного ListView вместе с разными типами строк, чтобы создать иллюзию наличия вкладок в ListView, содержащих другие ListViews, и все они обрабатываются специальным адаптером. Исходя из вашего примера, у вас будет четыре типа строк:

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

Чтобы реализовать эти типы строк, вам нужно будет использовать метод getItemViewType() и getViewTypeCount() адаптера:

// different row types
private static final int NORMAL_ROW = 0;
private static final int TAB_ROW = 1;
private static final int TAB1_TYPE = 2;
private static final int TAB2_TYPE = 3;

@Override
public int getItemViewType(int position) {
    if (position < mData.size()) {
            // we are in the initial list's range so it's a normal row
        return NORMAL_ROW;
    } else if (position == mData.size()) {
        // we are at the tab level, so it's a tab row
        return TAB_ROW;
    } else {
        // based on the current selected tab(0 by default) we have
        // either a tab 1 row type or tab 2 row type
        return mCurrentSelectedTab == 0 ? TAB1_TYPE : TAB2_TYPE;
    }

}

@Override
public int getViewTypeCount() {
    // if your list-tabs need different row types then you'll need to
    // make the calculations here and update appropriately
    return 4;
}

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

Вы можете увидеть полный образец здесь, также взгляните на используемые макеты XML. быть достаточно простым для понимания.

person user    schedule 29.04.2013
comment
Это именно то, что мне нужно. Огромное спасибо. Теперь осталось выучить код :) - person Favolas; 30.04.2013
comment
Привет. Мне удалось заставить код, который вы предоставили, работать с 7 типами строк. TAB3_TYPE и TAB4_TYPE и начальная строка INIT_ROW, которая увеличивается в начале основного списка getItemViewType(int position) { if (position == 0) { return INIT_ROW;}…Я знаю, что хочу увеличить строку нового типа. Эта строка должна располагаться в конце 4-х списков, которые отображаются при использовании вкладок. Можете ли вы указать мне какое-то направление? Я пробовал кучу вещей, но ничего не помогло :( - person Favolas; 09.05.2013