我已经完成了有关此事的所有研究。我知道谷歌认为这是没有意义的,开发人员知道事实并非如此。我也知道没有已知的解决方法,但我知道我接近制作一个。用户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);
}
}
这几乎为我完成了工作。但是当我尝试它时,我在listItem.measure(0,0)行得到一个NullPointer异常。 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方法中时,事件不会被触发,也不会在我的Activity的onWindowFocusChanged方法中触发。我尝试了一个自定义事件,但它从未触发过(它放在我的自定义视图的onWindowFocusChanged方法中,并且监听器在我的Activity的onWindowFocusChanged方法中)。
答案 0 :(得分:9)
好的,就我满足您的需求而言,我认为您可以使用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 :(得分:1)
出于好奇,您的布局是否使用RelativeLayout?如果是这样,调用measure(0,0)
将始终抛出NPE,但LinearLayout不会。
http://groups.google.com/group/android-developers/browse_thread/thread/5a947482d7dcb605
将其更改为线性,您可以拨打该电话。我希望有所帮助!
我的应用程序中有一个情况,我有段落的文本,图像视图,给定主题的各种信息...然后,根据项目,可能一个ListView所有信息中间的比较数据。每10个项目中就有一个拥有它,它位于所有文本之间。比较数据最多不超过4个项目,所以我不想希望 ListView滚动。我只希望ListView在我指定的确切位置完整显示。
将它们全部添加为嵌套的线性布局是疯狂的,因此当我甚至在屏幕上没有ListView时,使用MergeAdapter将所有这些放在一起。并使用复杂的ListView标题和&amp;页脚也是不可能的。
我不是第一个想要这种功能的人,我不会是最后一个。上面的解决方案几乎是完美的,它调整我的ListView的大小,使其在屏幕上显示完整,并且所有滚动都来自ScrollView父级。 (这很容易在iOS SDK上犯罪,顺便说一下,那里有很多类似的东西;我们需要一个很好的解决方案。)