ListView в ScrollView потенциальный обходной путь - PullRequest
2 голосов
/ 04 ноября 2010

Я провел все исследования по этому вопросу.Я знаю, что Google считает это бессмысленным, и что разработчики знают, что это не так.Я также знаю, что нет известного обходного пути, но я знаю, что близок к его созданию.Пользователь DougW разместил этот код:

public class Utility {
    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }
}

, который почти выполняет работу за меня.Но когда я пытаюсь это сделать, я получаю исключение NullPointer в строке listItem.measure (0, 0).Сам listItem инициализируется, но метод все равно выдает исключение.Пожалуйста, скажите мне, как я могу это исправить.

Вот мой код:

public class ExpenseReportsActivity extends Activity {

    private ListView lvReports;
    private ExpenseReportListAdapter adapter;
    private Button btnSend;
    private Button btnCancel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.expensereports);

        lvReports = (ListView)findViewById(R.id.lv_reports);
        lvReports.setBackgroundResource(R.drawable.shape_expense_report_list);

        ColorDrawable cd = new ColorDrawable(0xFFffffff);
        lvReports.setDivider(cd);
        lvReports.setDividerHeight(1);

        adapter = new ExpenseReportListAdapter(this);
        lvReports.setAdapter(adapter);

        int totalHeight = 0;
        for (int i = 0; i < adapter.getCount(); i++) {
            View listItem = adapter.getView(i, null, lvReports);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = lvReports.getLayoutParams();
        params.height = totalHeight + (lvReports.getDividerHeight() * (adapter.getCount() - 1));
        lvReports.setLayoutParams(params);
    }
}

Другой обходной путь, над которым я работаю, использует метод onWindowFocusChanged моего пользовательского представления.Он сообщает точную высоту вида.Проблема заключается в том, что событие не вызывается, пока я все еще в методе Activiy onCreate или в методе onWindowFocusChanged моего Activity.Я попробовал пользовательское событие, но оно никогда не срабатывало (оно было помещено в метод onWindowFocusChanged моего пользовательского представления, а слушатель находился в методе onWindowFocusChanged моей Activity).

Ответы [ 2 ]

9 голосов
/ 07 ноября 2010

Хорошо, насколько я понимаю ваши потребности, я думаю, вы можете просто использовать метод ListView.addFooterView(View v):

http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)

Это позволит вам прокручивать все элементы списка + нижний колонтитул «несколько кнопок» как один блок.

Так что код должен быть таким:

import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;

public class YourActivity extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LayoutInflater factory = getLayoutInflater();
        LinearLayout footer = 
            (LinearLayout) factory.inflate(R.layout.your_a_few_buttons_footer, null);

        getListView().addFooterView(footer);

        String[] array = new String[50];
        for (int i = 0; i < 50;) { array[i] = "LoremIpsum " + (++i); }

        setListAdapter(
            new ArrayAdapter<String>(this, R.layout.list_item, array)
        );
    }   
}

Обратите внимание, док говорит, что addFooterView() должен называться ДО setListAdapter().

ОБНОВЛЕНИЕ : чтобы добавить View вверху списка, используйте ListView.addHeaderView(View v). Обратите внимание, что, например, LinearLayout также является View. Таким образом, вы можете поместить все, что захотите, в верхний или нижний колонтитул, и он будет прокручиваться со списком как неделимый блок.

1 голос
/ 09 ноября 2010

Из любопытства ваш макет использует RelativeLayout?Если это так, то вызов measure(0,0) всегда вызовет NPE, но LinearLayout - нет.http://groups.google.com/group/android-developers/browse_thread/thread/5a947482d7dcb605

Измените его на Linear, и вы сможете сделать этот вызов.Я надеюсь, что это поможет!


В моем приложении есть ситуация, когда у меня есть абзацы текста, изображения, всякая информация по заданной теме ... и затем, в зависимости от элемента, возможно ListView сравнения данных в середине всей этой информации.Приблизительно один из каждых 10 пунктов имеет его, расположенный между всем текстом.Максимальное количество сравниваемых данных - не более 4 элементов, поэтому я не хочу ListView для прокрутки.Я просто хочу, чтобы ListView полностью отображался в той точке, которую я указал.

Добавление их всех как вложенных линейных макетов - безумие, поэтому я использую MergeAdapter, чтобы собрать все это вместе, когда у меня даже нетListView на экране.И об использовании сложных верхних и нижних колонтитулов ListView также не может быть и речи.

Я не первый человек, который хочет такую ​​функциональность, и я не буду последним.Вышеупомянутое решение почти идеально, оно масштабирует мой ListView так, чтобы оно было полноэкранным, и вся прокрутка происходит от родителя ScrollView.(Это легко сделать на iOS SDK, между прочим, и многие другие приложения делают подобные вещи; для этого нам понадобится хорошее решение.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...