Manchmal könnte ich ausrasten, wenn ich mit XML-Layouts von Android arbeite. Besonders bei trivialen Anforderungen, die einfach so funktionieren sollten. Heute hatte ich folgendes Problem:
Ich wollte 2 Listviews passgenau in einem Navigation-Drawer platzieren, jedoch wurde mir nur ein Eintrag jeder Liste angezeigt. (Siehe Abbildung rechts) Theoretisch hätte es mit den Attributen
<ListView android:id="@+id/NavigationDrawer_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#cccc" android:choiceMode="singleChoice" android:divider="@android:color/white" android:dividerHeight="1dp" />
funktionieren sollen. Jedoch stellte sich heraus, dass eine Listview noch einmal in einer ScrollView eingepackt ist und das Attribut „android:layout_height“ mit dem Parameter wrap_content nicht funktioniert. Aus diesem Grund habe ich mir folgende Methode geschrieben.
Die Methode hat eine ganz einfache Aufgabe – Sie ermittelt die reale Höhe der Listview und aktualisiert diese.
/** Berechnet die Hoehe einer Listview aufgrund seiner Eintraege. * @param listView die Liste */ private void setListViewHeight(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { throw new IllegalArgumentException("ListView beinhaltet keinen ListAdapter"); } int totalHeight = 0; int desiredWidth = 0; // Breite der Liste bestimmen // +++ ACHTUNG +++ BITTE DIE RICHTIGE METHODE AUSWAEHLEN!!!!!!! // Methode fuer eine Activity desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST); // Wenn die Variable "desiredWidth" -21212.. ist, dann nur mit listView.getWidth() oder mit einem anderen Element arbeiten! // Methode fuer eine Liste in einem Naviagation-Drawer //desiredWidth = Math.round(getActivity().getResources().getDimension(R.dimen.navigation_drawer_width)); // fuer jedes Element die Groesse bestimmen und dazu addieren for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED); totalHeight += listItem.getMeasuredHeight(); } // neue Hoehe der Listview setzen und Element aktualisieren ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); }
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // View holen View v = inflater.inflate(R.layout.navigation_drawer_fragment, container, false); // Listen holen ListView list1 = (ListView) v.findViewById(R.id.NavigationDrawer_list); ListView list2 = (ListView) v.findViewById(R.id.NavigationDrawer_list2); // irgendwie einen Adapter setzen ;-) mDrawerListView.setAdapter(new ArrayAdapter<String>(getActionBar().getThemedContext(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, new String[] { getString(R.string.title_section1), getString(R.string.title_section2), getString(R.string.title_section3), })); omg.setAdapter(new ArrayAdapter<String>(getActionBar().getThemedContext(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, new String[] { getString(R.string.title_section1), getString(R.string.title_section2), getString(R.string.title_section3), getString(R.string.title_section3), getString(R.string.title_section3) })); // die neue Methode aufrufen! setListViewHeight(list1); setListViewHeight(list2); return v; }
Wenn ihr einen eigenen Adapter schreibt müsst ihr darauf achten, dass ihr den „parent“ mit beachtet!!! Sonst kommt: android.view.InflateException: Binary XML file line #14: Error inflating class fragment
public View getView(int position, View convertView, ViewGroup parent) { convertView = layoutInflater.inflate(R.layout.dein_layout, parent, false);
Wenn nichts mehr geht und die Funktion nicht funktioniert. Erstell einfach ein leeres LinearLayout und nutze diese Funktion:
MeinListAdapter myAdapter = new MeinListAdapter(getActivity(), myList); LinearLayout ll = (LinearLayout) v.findViewById(R.id.NavigationDrawer_ll); for (int i = 0; i < myAdapter .getCount(); i++) { View listItem = myAdapter .getView(i, null, ll); listItem.setClickable(true); listItem.setOnClickListener(new meinListener(getActivity(), myList.get(i))); ll.addView(listItem); if(i < (myAdapter .getCount() - 1)){ View trenner = new View(getActivity()); float density = getActivity().getResources().getDisplayMetrics().density; float px = 1 * density; trenner.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, Math.round(px))); trenner.setBackgroundColor(Color.GRAY); ll.addView(trenner); } } ll.requestLayout();
Copyright © 2014 AxxG – Alexander Gräsel
Ein sehr erstklassiger Post, der alles hervorragend zusammen fasst. Ich habe mich damals auch durch alle Anfänger-Guides gelesen bevor ich dann nutzliche Mitteilung gefunden habe. Bei mir ist es immer so, dass ich die meisten Empfehlungen für mehr Einflussbereiche zwar kenne, aber dann doch nicht umsetzte. So einen Publikation zu lesen motiviert dann wieder – habe ich gedacht und bin weiter gesurft. Sowas ist äußerst dienstbeflissen! Aber es gibt noch ein Thema dazu – Virtuelle Datenräume. Es ist vor allem schön zu wissen, dass alle mal klein angefangen habe. Das ist zwar eigentlich klar, aber wird gern vergessen.