ListView set contents gravity to right - android

I have a Fragment in which there is a ListView.
The ListView is populated using a simple ArrayAdapter which its code is below.
I want the ListView to show it's content from RIGHT to LEFT.
(I want each row of ListView to set its text to its right)
The gravity set to right seems to do nothing.
I tried a couple of solutions suggested in here but I don't know why no matter what change I make I don't see any difference.
I have changed width of ListView and Layouts to match_parent, fill_parent, wrap_content... nothing changed.
My Activity xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context="com..SearchResultListActivity"
tools:ignore="MergeRootFrame"/>
My Fragment xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:layout_gravity="right"
android:gravity="right"
android:orientation="vertical"
tools:context="com.***.SearchResultListActivity$PlaceholderFragment" >
<ListView
android:id="#+id/listViewSearchResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right">
</ListView>
</LinearLayout>
My Activity Class:
public class SearchResultListActivity extends ActionBarActivity {
//LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
//ArrayList<String> listItems=new ArrayList<String>();
//DEFINING A STRING ADAPTER WHICH WILL HANDLE THE DATA OF THE LISTVIEW
//ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result_list);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_result_list, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
String[] array = new String[] {"cat", "dog", "mouse"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, array);
ListView listView = (ListView) getActivity().findViewById(R.id.listViewSearchResult);
listView.setAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_search_result_list, container, false);
return rootView;
}
}
}

You are using the android list item layout, that's why you are not seeing the content correctly, also because you have changed the gravity of the ListView itself, not its content. You should set the gravity of the items, and they must be declared in a new layout file with a custom adapter.
First of all remove the android:layout_gravity="right" from your Fragment xml layout, it won't be needed anymore.
Also your ListView width must be set to match_parent.
Change your Fragment.xml layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.***.SearchResultListActivity$PlaceholderFragment" >
<ListView
android:id="#+id/listViewSearchResult"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
Now you must create a new layout to represent the items of your ListView.
1. Create a list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_item_row"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="right"
android:padding="10dp">
<TextView android:id="#+id/txtTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:textStyle="bold"
android:textSize="22dp"
android:textColor="#000000"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
</LinearLayout>
As you can see, we set the layout_gravity of the item in this layout, this way the content of your Listview will have this behavior, to be in the right of the ListView.
2. Create custom array adapter class as inner class
Also you must create a custom Adapter to inflate the layout and set the values correctly. This is how your Activity should look with the custom array adapter as inner class
public class SearchResultListActivity extends ActionBarActivity {
//LIST OF ARRAY STRINGS WHICH WILL SERVE AS LIST ITEMS
//ArrayList<String> listItems=new ArrayList<String>();
//DEFINING A STRING ADAPTER WHICH WILL HANDLE THE DATA OF THE LISTVIEW
//ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result_list);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_result_list, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
String[] array = new String[] {"cat", "dog", "mouse"};
// Here we initialize the custom array adapter sending the proper values to the constructor
MyArrayAdapter adapter = new MyArrayAdapter(getActivity(), R.layout.list_item, array);
ListView listView = (ListView) getActivity().findViewById(R.id.listViewSearchResult);
// Here we set the custom adapter to the Listview
listView.setAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_search_result_list, container, false);
return rootView;
}
}
// This is the custom adapter class where you will manage the behavior of your ListView content
public class MyArrayAdapter extends MyArrayAdapter<String>{
Context context;
int layoutResourceId; // This is the layout you created for the list items
String data[] = null; // the array with the data to populate the listview
public MyArrayAdapter(Context context, int layoutResourceId, String[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
// Here we inflate the list item layout to load its views (the TextView)
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
// Now we can get the TextView from the layout
TextView txtTitle = (TextView)row.findViewById(R.id.txtTitle);
// Here we set the value from a specific position in the array
txtTitle.setText(data[position]);
return row;
}
}
}
3. Initialize your adapter
Now you must initialize your adapter based on the custom adapter you created before, like this.
MyArrayAdapter adapter = new MyArrayAdapter(getActivity(), R.layout.list_item, array);
As you can see here we send the custom list_item.xml layout and the array with the data you want to populate also the context on the constructor.
4. Set the adapter to your listview
Now you must set the adapter you created before to your ListView
listView.setAdapter(adapter);
Let me know if you have more doubts.
Hope it helps you.

You have changed the gravity of the ListView container but not the rows it contains as I assume you wanted to.
It's a little unclear whether you want right aligned text or text that gets populted from the right to the left. Either way the solution is the same.
The best solution would be to copy the code from android.R.layout.simple_list_item_1 into your own layout and change the properties of the TextView in there. (Ensure that you keep the View's id the same unless you want to change more of your Adapter code.)
You can find the built-in layouts at <android-sdk-root>/platforms/<version>/data/res/layout/.
Then load your adapter with:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getActivity(),
R.layout.my_simple_list_item, // use your layout
array);
The v19 simple_list_item_1 for reference:
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
/>

Related

Android custom listview intents How to let it work?

I made a custom listView and custom array adapter with 1 image and 2 textviews. What I want to work is when you click on an item in the listview that it opens a new activity with an intent.
this is the mainactivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.?_main);
ListView listView = (ListView) findViewById(R.id.list);
ArrayList<Subjects> obsclassiclist = new ArrayList<Subjects>();
obsclassiclist.add(new Subjects("?", "?", R.mipmap.ic_launcher));
obsclassiclist.add(new Subjects("?", "?", R.mipmap.ic_launcher));
WordAdapter adapter = new WordAdapter(this, obsclassiclist);
listView.setAdapter(adapter);
LinearLayout listViewIntent = (LinearLayout) findViewById(R.id.intent);
listViewIntent.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int
position, long id) {
if (position==0) {
Intent tutorial = new Intent(view.getContext(),
Cl_01.class);
// Start the new activity
startActivityForResult(tutorial,0);
}
if (position==1) {
Intent requirements = new Intent(view.getContext(),
CL_02.class);
// Start the new activity
startActivityForResult(requirements,1);
}
}
});
}
}
this the custom adapter
public WordAdapter(Activity context, ArrayList<Subjects> subjects) {
// Here, we initialize the ArrayAdapter's internal storage for the context
and the list.
// the second argument is used when the ArrayAdapter is populating a single
TextView.
// Because this is a custom adapter for two TextViews and an ImageView, the
adapter is not
// going to use this second argument, so it can be any value. Here, we used
0.
super(context, 0, subjects);
}
/**
* Provides a view for an AdapterView (ListView, GridView, etc.)
*
* #param position The position in the list of data that should be displayed
in the
* list item view.
* #param convertView The recycled view to populate.
* #param parent The parent ViewGroup that is used for inflation.
* #return The View for the position in the AdapterView.
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.list_item, parent, false);
}
// Get the {#link subject} object located at this position in the list
Subjects currentSubjects = getItem(position);
// Find the TextView in the list_item.xml layout with the ID subject
TextView subjectTextView = (TextView)
listItemView.findViewById(R.id.subject);
// Get the version name from the current wordadapter object and
// set this text on the subject TextView
subjectTextView.setText(currentSubjects.getObsclassicSubject());
// Find the TextView in the list_item.xml layout with the ID description
TextView descriptionTextView = (TextView)
listItemView.findViewById(R.id.description);
// Get the version number from the current wordadapter object and
// set this text on the description TextView
descriptionTextView.setText(currentSubjects.getObsclassicDescription());
// Find the Imageview in the list_item.xml layout with the ID version_number
ImageView pictureImageView = (ImageView)
listItemView.findViewById(R.id.image);
// Get the version number from the current wordadapter and
// set this image on the imageview
pictureImageView.setImageResource(currentSubjects.getObsclassicimageid());
// Return the whole list item layout (containing 2 TextViews and an
ImageView)
// so that it can be shown in the ListView
return listItemView;
}
}
here is the xml custom listview
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="80dp"
android:id="#+id/intent"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/image"
android:scaleType="centerInside"
android:src="#mipmap/ic_launcher"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingTop="10dp"
android:textSize="20sp"
android:textStyle="bold"
android:id="#+id/subject"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingBottom="10dp"
android:textSize="18sp"
android:textStyle="italic"
android:id="#+id/description"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
and the xml from the main activity
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list">
</ListView>
if somebody has a solution pls let me know
You are doing wrong, your are making clicklistener on linear layout, instead do it on ListView
Change this
listViewIntent.setOnItemClickListener(new
AdapterView.OnItemClickListener()
To
listView .setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3)
{
Toast.makeText(SuggestionActivity.this, "" + position, Toast.LENGTH_SHORT).show();
// Now if you want to startActivity
Intent tutorial = new Intent(MainActivity.this,
Cl_01.class);
// Start the new activity
startActivityForResult(tutorial,position);
}
});

Fragment Class with ListView?

Is it possible to have custom ListView inside Fragment class?
This is my fragment class wherein the fragment_find_people is just an empty XML:
public class FindPeopleFragment extends Fragment {
public FindPeopleFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_find_people, container, false);
return rootView;
}
}
Now, I've already have a customListView but it only works with the Activity class. How can I transfer that to Fragment?
my listview_main xml
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/listmain" >
<ListView
android:id="#+id/listview"
android:layout_marginTop="10dp"
android:background="#drawable/bg"
android:divider="#9c9c9c"
android:dividerHeight="5dp"
android:layout_width="fill_parent"
android:layout_height="fill_parent" /></RelativeLayout>
Class context replace with getActivity thats only difference and replace view not activity:
View rootView = inflater.inflate(R.layout.fragment_find_people, container, false);
//now you must initialize your list view
Listview listview =(Listview)rootView .findViewById(R.id.your_listview);
//EDITED Code
String[] items = new String[] {"Item 1", "Item 2", "Item 3"};
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
listview.setAdapter(adapter);
//To have custom list view use this : you must define CustomeAdapter class
//listview.setadapter(new CustomeAdapter(getActivity()));
//getActivty is used instead of Context
return view;
Inside the onCreateView method first define your layout.
RelativeLayout rl=(RelativeLayout)inflater.inflate(R.layout.status,container, false);
list=(ListView) rl.findViewById(R.id.list1);
itemList = new ArrayList<HashMap<String, String>>();
// fill the defined arraylist using and asynctask or any other method
adapter=new Customadapt(context.getActivity(), itemList);
list.setAdapter(adapter);
return rl;
you can create your custom list view programmatically also. for ex:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return new CustomListView(container.getContext());
}
Inside onCreateView(...) method, call your CustomListAdapter like this
adapter = new CustomListAdapter(getActivity());
customListView.setAdapter(adapter);
And your CustomListAdapter as follows , e.g
private class CustomListAdapter extends BaseAdapter {
LayoutInflater inflater;
public Context context;
public CustomListAdapter(Context context) {
this.context = context;
inflater = LayoutInflater.from(this.context);
}
.......
.......
}
First off, yes, it is possible. Here is how.
As with all other resources, there are two ways to declare them. Programatically and via XML layout files. I'll explain using XML as it is what I use most often and I find best.
In your fragment_find_people XML, declare your layout as normal. In that layout, I presume at least a LinearLayout, you need to add a ListView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_find_people_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#id/your_list_view_id"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
Now you can just instantiate that ListView using:
Listview listView =(ListView)rootView.findViewById(R.id.your_list_view_id);
In order to use the "same" ListView, I would recommend simply duplicating the code of the ListView from one layout file, the one for your Activity to the Fragment. You could also separate the declaration of the ListView into a separate XML, which would be tidier if you'd be to reuse it a lot, but for a small project, just copy it.

Android: button showing up multiple times in list view

I trying to write code to highlight the selected value of the list with "Next" button at the bottom of the layout. But for some reason, after every list item, "next" button also shows up. Can someone please help me resolve this problem?
Here is the layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/questionLayout"
>
<TextView android:id="#+id/txtExample"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="#000000"
android:background="#FF0000"
/>
<ListView
android:id="#+id/listExample"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#CCCCCC"
android:choiceMode="singleChoice"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<Button
android:id = "#+id/next"
android:text="Next"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity="center"
android:layout_weight="50"
/>
<Button
android:id = "#+id/submit"
android:text="Submit"
android:layout_width = "0dp"
android:layout_height = "wrap_content"
android:layout_weight="50"
android:layout_gravity="center"
/>
</LinearLayout>
</LinearLayout>
Java Code:
public class updateList extends Activity {
private SelectedAdapter selectedAdapter;
private ArrayList<String> list;
int correct_answer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<String>();
list.add("Choice One");
list.add("Choice Two");
list.add("Choice Three");
selectedAdapter = new SelectedAdapter(this,0,list);
selectedAdapter.setNotifyOnChange(true);
ListView listview = (ListView) findViewById(R.id.listExample);
listview.setAdapter(selectedAdapter);
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view,
int position, long id) {
// user clicked a list item, make it "selected"
selectedAdapter.setSelectedPosition(position);
}
});
}
}
Thanks in advance
SSP
Selected Adaptor class:
public class SelectedAdapter extends ArrayAdapter{
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
public SelectedAdapter(Context context, int textViewResourceId,
List objects) {
super(context, textViewResourceId, objects);
}
public void setSelectedPosition(int pos){
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition(){
return selectedPos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
// only inflate the view if it's null
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.activity_main, null);
}
// get text view
TextView label = (TextView)v.findViewById(R.id.txtExample);
// change the row color based on selected state
if(selectedPos == position){
label.setBackgroundColor(Color.CYAN);
}else{
label.setBackgroundColor(Color.WHITE);
}
label.setText(this.getItem(position).toString());
/*
// to use something other than .toString()
MyClass myobj = (MyClass)this.getItem(position);
label.setText(myobj.myReturnsString());
*/
return(v);
}
}
change your listview in xml as like this
<ListView
android:id="#+id/listExample"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"//===== set maximum heighthere
android:layout_marginBottom="50dp"// === give some space at bottom so that buttons will appear
android:background="#CCCCCC"
android:choiceMode="singleChoice"
/>
But for some reason, after every list item, "next" button also shows up.
The ListView's row layout is determined by the layout you inflate in getView() or pass to your Adapter's super class if you haven't overridden getView(). Double check this layout and remove the unwanted code.
Addition
The layout for your ListView's items only needs to be one TextView since you only want to display a phrase in each. However you are currently passing your entire main layout, this creates the Buttons, an unused ListView, and everthing else in every row...
Instead use android.R.layout.simple_list_item_1 in getView(), of course you'll need to change the id you pass to findViewById() as well:
if (v == null) {
LayoutInflater vi = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(android.R.layout.simple_list_item_1, null);
}
// get text view
TextView label = (TextView)v.findViewById(android.R.id.text1);
Please watch Android's Romain Guy discuss writing an efficient adapter to speed things up.

Support ListFragment issue

I'm currently using a ListFragment together with an ExpandableListView to show some data backed by a SimpleCursorTreeAdapter. Everything works fine, but I recently switched to the support.v4 package, to make use of the ViewPager class to swipe between tabs. Swiping and all the other classes that now use the support.v4.Fragment work fine, but my ListFragment has stopped working.
There are no exceptions thrown, but the ListFragment simply doesn't show any items.
This is the code for the ListFragment:
public class VisuTextFragment extends ListFragment {
private Storage mStorage;
private int mFilterSensortype;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mStorage = Storage.newSQLiteDatabase(getActivity());
mFilterSensortype = -1;
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.l_visu_text, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fillData();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.textvis, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_filter:
final Dialog dialog = new Dialog(getActivity());
dialog.setTitle("Filter by sensor type");
dialog.setContentView(R.layout.l_dialog_filter);
Button ok = (Button) dialog.findViewById(R.id.filter_ok);
ok.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int filter = Integer.parseInt(((EditText) dialog.findViewById(R.id.et_filter)).getText().toString());
mFilterSensortype = filter;
fillData();
dialog.dismiss();
}
});
Button cancel = (Button) dialog.findViewById(R.id.filter_cancel);
cancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
dialog.cancel();
}
});
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
dialog.show();
break;
}
return true;
}
#Override
public void onResume() {
super.onResume();
fillData();
}
public void fillData() {
Log.d("VisuTextFragment", "fillData()");
Cursor cursor;
if (mFilterSensortype == -1)
cursor = mStorage.queryAllAsCursor();
else
cursor = mStorage.query(mFilterSensortype);
TextVisCursorAdapter adapter = new TextVisCursorAdapter(
getActivity(),
cursor,
R.layout.l_visu_text_group,
new String[] { Storage.ELEMENT_ID, Storage.ELEMENT_ENTRIES_DATE, Storage.ELEMENT_ENTRIES_LATITUDE, Storage.ELEMENT_ENTRIES_LONGITUDE, Storage.ELEMENT_ENTRIES_SENSORTYPE },
new int[] { R.id.id, R.id.date, R.id.latitude, R.id.longitude, R.id.sensortype },
R.layout.l_visu_text_child,
new String[] { Storage.ELEMENT_MEASUREMENTS_VALUE },
new int[] { R.id.value });
ListView lv = (ListView) getListView();
ExpandableListView elv = (ExpandableListView) lv;
elv.setGroupIndicator(null);
elv.setAdapter(adapter);
}
}
And this is the layout that I'm using (don't know if that helps):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/id"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="#string/date"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="#string/latitude"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="#string/longitude"/>
<TextView
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/sensortype"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ExpandableListView android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transcriptMode="normal"/>
<TextView android:id="#+id/android:empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/no_entries"/>
</LinearLayout>
</LinearLayout>
Just FYI: The TextView's in the layout file are shown, but the list itself is just missing. Not even the TextView for an empty list is shown.
Hope you can help.
EDIT: I have checked for the ExpandableListView's width and height via their corresponding methods and both return a value of 0. Its getCount() method returns 347. So the View definitely exists and is filled properly, but it is for some weird reason just not drawn to the screen.
EDIT2: Ok I fixed the problem. The problem was that the LinearLayout that hosted the TextViews on top of the actual list had its layout_height attribute set to fill_parent, which strangely was no issue for the non-support version as well as the composer in eclipse, since they both worked that way and I didn't even notice that it was set to fill_parent.
getListView() in a ListFragment is specifically looking for a listview id of #id/android:list. I'm not sure that adding the "+" in there like you did would have an effect or not, but it's the first thing I would try.
You also note you switched to the support library... did you switch all the appropriate method calls? For example, instead of getFragmentManager you would need to use getSupportFragmentManager and instead of using an Activity to control the fragments, you would need to use FragmentActivity, etc.
I think that that its butter to use android:id="#android:id/list" instead of android:id="#+id/android:list", also, in your case its really useless to extend ListFragment, just use Fragment and use findViewById for your expandableList.
Can you change:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
to:
public void onActivityCreated(Bundle aSavedInstanceState) {
super.onActivityCreated(aSavedInstanceState);
fillData();
}
make sure that your fillData method is called.
Ok I fixed the problem. The problem was that the LinearLayout that hosted the TextViews on top of the actual list had its layout_height attribute set to fill_parent, which strangely was no issue for the non-support version as well as the composer in eclipse, since they both worked that way and I didn't even notice that it was set to fill_parent.

Android, issues with custom listview

I'm using a custom listview I found here:
http://developer.android.com/resources/samples/ApiDemos/res/layout/linear_layout_9.html
Seems to be valid in Eclipse, and looks good in the preview tab. It's just a listview that has a button on the bottom. So i've added it as R.layout.buttonlist
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="#+id/testbutton"
android:text="#string/hello" android:layout_alignParentBottom="true" />
<ListView android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/list"
android:layout_alignParentTop="true" android:layout_above="#id/testbutton" />
</RelativeLayout>
Unfortunately when I run it, i get a pop up window that says Android has closed unexpecitdly:
setListAdapter(new ArrayAdapter<String>(this, R.layout.buttonlist , data));
When I try using a built in list view:
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
everything works fine. I dont see any errors or warnings in logcat, so I'm not sure how to pinpoint the problem. Does anyone have any ideas? Thanks
Edit: adding activity
public class TestActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<String> data = new ArrayList<String>();
data.add("hello");
data.add("world");
setContentView(R.layout.buttonlist);
//setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
}
}
Hoofamon, I would like to correct you here. You are not creating a custom ListView but a custom layout with a ListView. Also, I believe that you have not completely understood what the setListAdapter is doing here.
This line that you have is telling the listview to consume 'android.R.layout.simple_list_item_1' as the content of its layout. This layout comes pre-defined in the Android SDK. It would just contain text in each item of a listview. The third attribute 'data' indicates the content of each listview item.
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
So, as Mike L. has suggested, if your intent is to have a listview with only text (having the default format), then the line above would serve the purpose well. You can set 'R.layout.buttonlist' as the layout of your activity using
setContentView(R.layout.buttonlist);
However, if you are planning to include additional content in the listview (read images) or want to change the styling of the text, you would have to define a custom layout for the listview. We can direct you to appropriate sources if you want to know how that can be done.
EDIT: A possible way of loading data into a normal ListView
TestActivity.java
public class TestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.buttonlist);
List<String> data = new ArrayList<String>();
data.add("hello");
data.add("world");
ListView mListView = (ListView)findViewById(R.id.list);
mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1 , data));
}
}
buttonlist.xml
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/testbutton"
android:text="#string/hello"
android:layout_alignParentBottom="true" />
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list"
android:layout_alignParentTop="true"
android:layout_above="#+id/testbutton" />
</RelativeLayout>
This is how it should look like on the emulator:
I don't think you can have a listview in the layout of an adapter. The passed in layout should just describe a row in the listview. So buttonlist should just contain the xml for the button. The listview needs to be in a separate layout file. If this is a list activity then you don't need another layout file, just call setListAdapter like you are doing.
If you want to use your R.layout.buttonlist to fill up your listview,you can do it as follows(your TestActivity should extend Activity,not ListActivity):
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.buttonlist);
String data[]=new String[]{"Item_1","Item_2","Item_3"}
Button b=(Button)findViewById(R.id.testbutton);
ListView lv=(ListView)findViewById(R.id.list);
ArrayAdapter aa=new ArrayAdapter(context,android.R.layout.simple_list_item_1, data);
lv.setAdapter(aa);
//Your code...
}
Now if you want to create custom listitem to be displayed in the listview,then you need to do like this:
Create your custom listitem xml file.
Ex: custom_listitem.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/icon"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/text"
/>
Create custom ArrayAdapter:
Ex. CustomArrayAdapter.class
public class CustomArrayAdapter extends ArrayAdapter<String> {
String[] array;
LayoutInflater mInflater;
public CustomArrayAdapter(Context context, int textViewResourceId,
String[] objects)
{
super(context, textViewResourceId, objects);
array=objects;
mInflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if(convertView==null)
{
convertView = mInflater.inflate(R.layout.custom_listitem, null);
holder = new ViewHolder();
holder.text=(TextView)convertView.findViewById(R.id.text);
holder.img=(ImageView)convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.text.setText(array[position]);
if(position==0)
holder.img.setImageResource(R.drawable.img1);
else if(position==1)
holder.img.setImageResource(R.drawable.img2);
else if(position==2)
holder.img.setImageResource(R.drawable.img3);
return convertView;
}
static class ViewHolder
{
TextView text;
ImageView img;
}
}
Use this custom adapter class in your main activity to fill up listview:
Be sure,this main activity extends Activity and not ListActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
context=getApplicationContext();
lv=(ListView)findViewById(R.id.listview);
CustomArrayAdapter aa=new CustomArrayAdapter(context,R.layout.custom_listitem, new String[]{"item_1","item_2","item_3"});
lv.setAdapter(aa);
// other lines of code
.
.
.

Categories

Resources