Editing a TextView from ListAdapter? - android

I have a ListView, which is backed by an ArrayAdapter. They are defined as such:
ListView listView = (ListView)findViewById(R.id.listview);
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, R.layout.list_item);
listView.setAdapter(listAdapter);
list_item.xml contains the following:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:textSize="16sp">
</TextView>
What I would like to do when adding an item to the list, is edit the TextView associated with the item, like changing it's colour for example. How would I go about doing this?

You could override the method getView() of your ArrayAdapter (link to the reference) for example:
ListView listView = (ListView)findViewById(R.id.listview);
ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(this, R.layout.list_item){
public View getView (int position, View convertView, ViewGroup parent){
View v = super.getView(position,convertView,parent);
TextView tx = (TextView) v;
//do something with tx
return v;
}
};
listView.setAdapter(listAdapter);

You should go watch this Google I/O talk: http://www.google.com/events/io/2010/sessions/world-of-listview-android.html it explains the basics of ListView and how you would go about doing these sorts of things.

Related

Android: ArrayAdapter requires the resource ID to be a TextView?

I'm trying to implement a code in which a list of linear layouts are inserted in the list view by using the array adapter. Each linear layout contains two subviews. Here's the xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_item"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/list_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"/>
<TextView
android:id="#+id/list_label"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:padding="10dp"
android:textSize="16sp" />
</LinearLayout>
Now in the fragment I created a code snippet like this.
final String[] my_page_items = getResources().getStringArray(R.array.my_page_items);
int[] my_page_icons = {
R.mipmap.ic_about,
R.mipmap.ic_app_settings,
R.mipmap.ic_account_settings,
R.mipmap.ic_logout
};
LinearLayout[] items = new LinearLayout[my_page_items.length];
TextView[] labels = new TextView[my_page_items.length];
ImageView[] icons = new ImageView[my_page_icons.length];
for(int i=0; i<my_page_icons.length; i++) {
items[i] = (LinearLayout) LayoutInflater.from(getActivity().getApplication()).inflate(R.layout.list_item, null);
labels[i] = (TextView) items[i].findViewById(R.id.list_label);
icons[i] = (ImageView) items[i].findViewById(R.id.list_icon);
labels[i].setText(my_page_items[i]);
icons[i].setBackground(getResources().getDrawable(my_page_icons[i]));
}
setListAdapter(new ArrayAdapter<>(getActivity(), R.layout.list_item, items));
lv = getListView();
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
});
When I run this code, I get the the following in the logcat.
java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
How should this problem be solved?
In
new ArrayAdapter<>(getActivity(), R.layout.list_item, items)
R.Layout.list_item must be the id of a xml layout file containing only a TextView(the TextView can't be wrapped by another layout, like a LinearLayout, RelativeLayout etc!),
EDIT possible solution :
If you want your list row layout to be something a little different then a simple TextView widget use this constructor:
new ArrayAdapter<>(getActivity(), R.layout.list_item, R.id.id_of_your_textview items)
where you supply the id of a layout that can contain various views, but also must contain a TextView with and id(the third parameter) that you pass to your ArrayAdapter so it can know where to put the Strings in the row layout.

How do I center text in a spinner in Android

I have a Spinner in my LinearLayour.
I am trying to center text in spinner:
This is my XML for that element:
<Spinner
android:id="#+id/project_Spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginRight="50dp"
android:layout_marginLeft="50dp"
android:padding="1dip"
android:prompt="#string/spinner_title"
/>
the declaration of the spinner in the Activity:
// Creating adapter for spinner
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, NomProjets);
// Drop down layout style - list view with radio button
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// attaching data adapter to spinner
spinner.setAdapter(dataAdapter);
Thanks,
The component that actually creates the items for the Spinner is the adapter. So you should customize it (by overriding the getView() method) to return centered TextView widgets.
In your case, replace the new ArrayAdapter<String> ... initialization with this code:
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, NomProjets)
{
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
return setCentered(super.getView(position, convertView, parent));
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent)
{
return setCentered(super.getDropDownView(position, convertView, parent));
}
private View setCentered(View view)
{
TextView textView = (TextView)view.findViewById(android.R.id.text1);
textView.setGravity(Gravity.CENTER);
return view;
}
};
Matiash's answer works. Here is another way:
Actually the text in the spinner is wrapped in a TextView , so we can override the android.R.layout.simple_spinner_item.xml(which is located at sdk\platforms\android-xx\data\res\layout) , create an new xml in the /layout folder, adding an attribute:
android:gravity="center" to make the text in the TextView center.
such like this:

Text color by programmatically created grid view content

I understand how to do this in design view, but I'm not sure how to create a style based on programmatically created elements. I followed a tutorial and here's where I'm at:
I have a grid view which is populated by a string array as in the code below:
...
gridView = (GridView) findViewById(R.id.gridView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strData);
gridView.setAdapter(adapter);
Each element of the string array populates the grid just fine.
How would I set the text color of the items added to the gridView?
2 solutions: dynamically or with a custom layout.
Dynamically: you can set a text color by using setTextColor(...) when you Override the getView() method in your ArrayAdapter, something like this:
gridview.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strData) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setTextColor(getResources().getColor(R.color.my_color));
return view;
}
});
Custom Layout: this is the simplest way, build a custom layout as:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tv"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:textColor="#color/my_color"
android:background="#drawable/my_background"
android:padding="5sp"
android:singleLine="true"
android:gravity="center" />
Then, set it to your adapter:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_layout_above, strData);
Even if, you wanted this dynamically, I'm not sure but I think it's better to do with a custom layout.
Hope this helps.
By creating a custom layout and supplying it to your ArrayAdapter. Currently you are supplying the default layout android.R.layout.simple_list_item_1. Create a new layout xml like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
And style it however you want.
You can use it like this:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.custom_layout, R.id.tvText, strData);

Android adding a relative view to a merge adapter

Hi i'm trying to add a relative view to a merge adapter but it's currently scrolling separetly to the lists so does anyone know how i can add a relative layout with an image view and a text view to a merge adapter?
my aim is to have it look like this
header(relativelyout red bar and title);
List
header(relativelyout red bar and title);
List
header(relativelyout red bar and title);
List
and to have this all scroll as if it was all one list
heres my attempt so far
arrayAdapter = new ArrayAdapter<String>(this, R.layout.single_item, newsList);
arrayAdapter2 = new ArrayAdapter<String>(this, R.layout.single_item, newsList2);
arrayAdapter3 = new ArrayAdapter<String>(this, R.layout.single_item, newsList3);
ListView list = getListView();
list.setTextFilterEnabled(true);
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE );
View header = inflater.inflate( R.layout.redcell, list, false);
setListAdapter (arrayAdapter);
adapter = new MergeAdapter();
adapter.addView(header);
adapter.addAdapter(arrayAdapter);
adapter.addView(header);
adapter.addAdapter(arrayAdapter2);
adapter.addView(header);
adapter.addAdapter(arrayAdapter3);
setListAdapter(adapter);
}
redcell.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/redcelllayout" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="30dp"
android:src="#drawable/titlerect" />
<TextView
android:id="#+id/redheadertext"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="left"
android:paddingLeft="15dp"
android:paddingTop="3dp"
android:textColor="#color/white"
android:textSize="15dp"
android:textStyle="bold"/>
</RelativeLayout>
Instead of creating them in the program, create an xml file for that view, inflate it, then add it to the adapter.
Like this:
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View header1 = inflater.inflate(R.layout.redbar_title);
View header2 = inflater.inflate(R.layout.redbar_title);
View header3 = inflater.inflate(R.layout.redbar_title);
adapter = new MergeAdapter();
adapter.addView(header1);
adapter.addAdapter(arrayAdapter);
adapter.addView(header2);
adapter.addAdapter(arrayAdapter2);
adapter.addView(header3);
adapter.addAdapter(arrayAdapter3);
setListAdapter(adapter);
Set each list layout_height to wrap_content, and wrap everything within a ScrollView.
Perhaps it would be easier if you could make your headers part of the adapter itself, as separators, and use a single list instead of 3.

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