I'm new here so i will try to explain my problems as good as i can.
I am trying to inflate a ListView into a View in my main activity. My main activity has some buttons and texts on the top of the Activity and there is enough space left for the listView. The listview is consisted of categories, represented as an imageView and a textview.
The problem im facing is that when i inflate the category_list_activity, the activity i created for the category list, two things happen:
The ListView takes over all the screen, which means i cannot touch neither the buttons nor the edittext, and also the ListView is empty.
I have created the Adapters needed and i have searched for some info here in stackof but i couldn't find any right answer.
Edit: due to solving the problem when the list was taking over the whole screen i remove the parts of code that is not needed.
The solution was to change the inflated activity's (activity_category_list.xml) height from "fill_parent" to "wrap_content". I also restricted the show code to the parts i think there is the problem about not loading the categories.
here is the parts of code i wrote:
MainActivity.java
public class MainActivity extends ActionBarActivity {
Activity a;
Button toogle_button;
Button go_button;
Button login_button;
EditText search_text;
View inflating_view;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
a = this;
inflating_view = findViewById(R.id.inflating_view);
ViewGroup parent =(ViewGroup) inflating_view.getParent();
int index = parent.indexOfChild(inflating_view);
parent.removeView(inflating_view);
inflating_view = getLayoutInflater().inflate(R.layout.activity_category_list, parent, false);
parent.addView(inflating_view, index);
inflating_view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast t = Toast.makeText(getApplicationContext(), "ListView clicked", Toast.LENGTH_SHORT);
t.show();
}
});
}
CategoryAdapter.java
private class Viewholder{
TextView category_text;
ImageView image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Viewholder holder = null;
Category category = categories.get(position);
if (convertView == null){
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(R.layout.activity_category, null);
holder = new Viewholder();
holder.category_text = (TextView) convertView.findViewById(R.id.category_text);
holder.image = (ImageView) convertView.findViewById(R.id.category_image);
convertView.setTag(holder);
}else{
holder = (Viewholder) convertView.getTag();
}
holder.category_text.setText(category.getName());
holder.image.setImageURI(category.getImageUri());
return convertView;
}
}
CategoryListActivity.java
public class CategoryListActivity extends ActionBarActivity {
ListView category_list_view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category_list);
Log.d("Category List View", "Category list view is called");
category_list_view = (ListView) findViewById(R.id.category_list_view);
CategoryAdapter ca = new CategoryAdapter(getApplicationContext(),
TestValues.categories);
category_list_view.setAdapter(ca);
category_list_view.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast toast = Toast.makeText(getApplicationContext(),
"Clicked Category" + parent.getItemIdAtPosition(position), Toast.LENGTH_LONG);
toast.show();
}
});
Log.d("Category List View", "Everything is loaded");
}
activity_main.xml
<RelativeLayout 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:background="#000000"
style="#android:style/Theme.Black.NoTitleBar"
tools:context="com.example.aggro.activities.MainActivity" >
<Button
android:id="#+id/toggle_button"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:text="#string/toogle_list_en"
android:textSize="10dp"
/>
<TextView
android:id="#+id/search_text_view"
android:layout_toRightOf="#+id/toggle_button"
android:layout_alignParentTop="true"
android:text="#string/search_text_en"
android:layout_height="30dp"
android:paddingTop="7dp"
android:textSize="10dp"
android:textColor="#FFFFFF"
android:layout_width="wrap_content"/>
<EditText
android:id="#+id/search_text"
android:layout_width="150dp"
android:layout_height="30dp"
android:layout_alignParentTop="true"
android:textColor="#FFFFFF"
android:textSize="15dp"
android:background="#000000"
android:layout_toLeftOf="#+id/search_go"
android:layout_toRightOf="#+id/search_text_view" />
<Button
android:id="#+id/search_go"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_toLeftOf="#+id/login_button"
android:layout_alignParentTop="true"
android:text="#string/search_go_en"
android:textSize="10dp" />
<Button
android:id="#+id/login_button"
android:layout_width="50dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="#string/login_en"
android:textSize="10dp" />
<View
android:id="#+id/inflating_view"
android:layout_below="#+id/toggle_button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</RelativeLayout>
I have checked the CategoryListActivity.java alone and it works as it was supposed to, so i think the adapter works right.
If you need any other information please let me know.
Thanks in advance.
Why are you using View instead of ListView in your activity_main.xml?
Change this part of activity_main.xml
<View
android:id="#+id/inflating_view"
android:layout_below="#+id/toggle_button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
by
<ListView
android:id="#+id/category_list_view"
android:layout_below="#+id/toggle_button"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
In your adapter replace
convertView = (View) inflater.inflate(R.layout.activity_category, null);
by
convertView = inflater.inflate(R.layout.activity_category, null);
No need to cast it.
Remove activity_category_list.xml and CategoryListActivity.java.
Initialize & use ListView & Adapter in MainActivity.java
Try this it will surely work.
In this case what you can do is, create a empty layout in your main activity xml. Set a ID for that. While inflating the listview, inflate it to that layout.
In activity_main.xml include a relative layout as follows. Your parent layout is relative_layout. Add another layout like this.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_below="#+id/login_button" > //make sure you use this property to tell where you want to place the view in the screen. This should be below your last button.
</RelativeLayout>
Since login_button is last button in your view, i have recommended,
android:layout_below="#+id/login_button"
Related
I have a ListView in one of my activities that I have bound to an ArrayList using a custom ArrayAdapter. I have set an OnItemClickListener to the ListView which should call a method that starts another activity. However, I find that when I click on the ListView items, it only sometimes works. Sometimes it will start the activity as it should; other times it seems to detect the click (the ripple effect appears on the list item) but does nothing; other times it doesn't even appear to detect the click (the ripple effect doesn't appear).
I've tried all the usual suggestions that I've come across: blocking descendants on the parent view item, setting clickable and focusable to false on all the components of the item views, setting isEnabled to return true in the custom adapter, etc, but the behavior remains the same. Any help appreciated. Here is the relevant code:
Activity containing the ListView:
public class ViewCollectionActivity extends AppCompatActivity {
private final String className = this.getClass().getSimpleName();
private CollectionHandler collectionHandler;
private Context context;
private ArrayList<Game> displayedCollection;
private GameCollectionAdapter collectionAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_collection);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
context = this;
collectionHandler = CollectionHandler.getInstance(this);
TextView view = null;
if (collectionHandler.getDisplayedCollection().size() > 0) {
view = (TextView) findViewById(R.id.no_items_textview);
view.setVisibility(View.GONE);
}
String currentDate = collectionHandler.getDateLastSynchronised();
view = (TextView) findViewById(R.id.last_updated_textview);
view.setText("Last synchronised: " + currentDate + " Total games: " + String.valueOf(collectionHandler.getDisplayedCollection().size()));
collectionAdapter = collectionHandler.getCollectionAdapter();
ListView listView = (ListView) findViewById(R.id.collection_list_view);
listView.setAdapter(collectionAdapter);
AdapterView.OnItemClickListener collectionItemClickListener = new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
launchGameDetailsActivity(position);
}
};
listView.setOnItemClickListener(collectionItemClickListener);
}
public void launchGameDetailsActivity(int position){
Log.d(className,"Starting lauchGameDetailsActivity method");
collectionHandler.setSelectedGame(position);
Intent intent = new Intent(this,ViewGameDetailsActivity.class);
startActivity(intent);
Log.d(className, "Ending lauchGameDetailsActivity method");
}
The XML for the activity:
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.bleachedlizard.ludome.viewcollection.ViewCollectionActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Synchronise Collection"
android:onClick="synchroniseCollection"/>
<TextView
android:id="#+id/last_updated_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Last synchronised: "
android:textAlignment="center"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Display Collection"
android:visibility="gone"
android:onClick="displayCollection"/>
<ListView
android:id="#+id/collection_list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</ListView>
<TextView
android:id="#+id/no_items_textview"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="You have no items in your collection."
android:textAlignment="center"
android:textSize="20sp"/>
</LinearLayout>
The XML for the item views:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/collection_item_layout"
android:layout_width="match_parent"
android:layout_height="75dp"
android:orientation="horizontal"
android:clickable="false"
android:descendantFocusability="blocksDescendants"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="#+id/collection_item_image"
android:layout_width="75dp"
android:layout_height="75dp"
android:src="#drawable/testimage"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
/>
<TextView
android:id="#+id/collection_item_name"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:padding="16dp"
android:singleLine="false"
android:textColor="#android:color/darker_gray"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
<TextView
android:id="#+id/collection_item_plays"
android:layout_width="100dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="8dp"
android:textColor="#android:color/darker_gray"
android:text="Plays: 0"
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:textIsSelectable="false"/>
</LinearLayout>
The code for the custom adapter:
public class GameCollectionAdapter extends ArrayAdapter<Game> {
private ArrayList<Game> collection;
public GameCollectionAdapter(Context context, int resource, ArrayList<Game> collection){
super(context, resource, collection);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout gameView = (LinearLayout) convertView;
LayoutInflater mInflater = LayoutInflater.from(getContext());
if (gameView == null) {
gameView = (LinearLayout) mInflater.inflate(R.layout.collection_item_view, null);
}
//Game game = collection.get(position);
Game game = super.getItem(position);
if (game != null) {
// This is how you obtain a reference to the TextViews.
// These TextViews are created in the XML files we defined.
TextView gameTitle = (TextView) gameView.findViewById(R.id.collection_item_name);
TextView numOfPlays = (TextView) gameView.findViewById(R.id.collection_item_plays);
ImageView thumbnail = (ImageView) gameView.findViewById(R.id.collection_item_image);
// check to see if each individual textview is null.
// if not, assign some text!
if (gameTitle != null){
gameTitle.setText(game.getTitle());
}
if (numOfPlays != null){
numOfPlays.setText("Plays: " + String.valueOf(game.getNumOfPlays()));
}
if (thumbnail != null){
thumbnail.setImageBitmap(game.getThumbnail());
}
}
// the view must be returned to our activity
return gameView;
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
I discovered what was causing the problem: the way I had set up the array that backed the ListView meant that it was downloading and storing the Bitmaps for every element in the array all the time. Once I changed the implementation so that it only downloaded the images as the ListView required them, then that seemed to improve performance and the onClickListener started to work fine.
The implementation I used was the exact same one shown here:
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I think the issue is due to the position of the item selection whenever you click you have an list position which is passed to your method launchGameDetailActivity(int position) check with log or toast on item click what all the position you are getting do the needful.
Here is my code try this like this if it helps.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(RecipeClass.this, "Position is" + position, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(RecipeClass.this, RecipeIngredients.class)
intent.putExtra("position", position);
startActivity(intent);
}
Check your arraylist value also whether they are not null.
What I'm trying to do is to have a listview item with a button in each list viewitem.
When the Buttton is being pressed I want a layout that is at gone state will be visible and expand with animation down, and if the layout is shown than when the same button is being preesed than the layout will slide up and be gone again.
In order to do so I've created the next layout for the listview item -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tilte_info">
<TextView
android:id="#+id/textView_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:text="TextView"
android:textSize="20sp" />
<Button
android:id="#+id/button_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="25dp"
android:text="Open" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#5C83AF"
android:visibility="gone"
android:id="#+id/extend_info">
<TextView
android:id="#+id/textView_more_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:text="TextView"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
As you can see there are two layouts - one is tilte_info which is always shown and have the button in it, and the other one is extend_info which will be shown or hide by the button click.
Now I've used the next code in order to try and make it work -
public class MainActivity extends Activity {
ArrayList<Place> placesList = new ArrayList<Place>();
placeAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Place place1 = new Place("Place num 1", "some info on place 1");
Place place2 = new Place("Place num 2", "some info on place 2");
Place place3 = new Place("Place num 3", "some info on place 3");
placesList.add(place1);
placesList.add(place2);
placesList.add(place3);
ListView lv = (ListView) findViewById(R.id.listview_1);
adapter = new placeAdapter(this);
lv.setAdapter(adapter);
}
class placeAdapter extends ArrayAdapter<Place> implements OnClickListener{
public placeAdapter(Context context) {
super(context, -1, placesList);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null){
// use the LayoutInflater to inflate an XML layout file:
convertView=getLayoutInflater().inflate(R.layout.list_item, parent,false);
}
TextView textTitle = (TextView) convertView.findViewById(R.id.textView_title);
TextView textInfo = (TextView) convertView.findViewById(R.id.textView_more_info);
Button open = (Button) convertView.findViewById(R.id.button_open);
infoLayout = (View) convertView.findViewById(R.id.extend_info);
infoLayout.setVisibility(View.GONE);
open.setOnClickListener(this);
Place place = placesList.get(position);
textTitle.setText(place.getTitle());
textInfo.setText(place.getInfo());
return convertView;
}
#Override
public void onClick(View v) {
if(infoLayout.isShown()){
slide_up(MainActivity.this, infoLayout);
infoLayout.setVisibility(View.GONE);
}else{
infoLayout.setVisibility(View.VISIBLE);
slide_down(MainActivity.this, infoLayout);
}
}
}
public static void slide_down(Context ctx, View v){
Animation a = AnimationUtils.loadAnimation(ctx, R.anim.slide_down);
if(a != null){
a.reset();
if(v != null){
v.clearAnimation();
v.startAnimation(a);
}
}
}
public static void slide_up(Context ctx, View v){
Animation a = AnimationUtils.loadAnimation(ctx, R.anim.slide_up);
if(a != null){
a.reset();
if(v != null){
v.clearAnimation();
v.startAnimation(a);
}
}
}
}
The thing is that I tried to debug the code and it getting into the onclick function but nothing is happening - the layout that is gone not been shown.
I've chacked the animation code with simple textview outside the listview and it worked, but when im trying to use it in the listview item, it doesn't work.
Any ideas why?
Thanks for any kind of help
Use ExpandableListView. You have to extend the BaseExpandableListAdapter to your adapter and override methods. In this methods, override getGroupView to display the name of expandablegroup and override getChildView method to inflate the child view for list. After inflating the layout for child, set whatever animation you want on that view.
you shoud use expandableview for it...
basic example fot that is here... expandavlelistview example
So I am using a custom ArrayAdapter implementation so that I have access to the toggle button inside my listview elements.
Each listview has a textview and a toggle button. I had to use a custom ArrayAdapter attached to the listview so that I could get the correct toggle button attached to the position of the listview that was clicked. Yet, each time I inflate the layout to get the view, the textview in the listview is disappearing. The values are still there, but the textview isnt. However the toggle buttons show up fine. This is the code used to inflate the layout and get the view:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
v = inflater.inflate(R.layout.activity_alarm_item, parent, false);
}
ToggleButton toggle = (ToggleButton) v.findViewById(R.id.alarm_status);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Log.d("ENABLE ALARM", Integer.toString(position));
enableAlarm(position);
} else {
disableAlarm(position);
}
}
});
return v;
}
Does something look wrong with the two lines that inflate the layout?
The layout is fine. I reverted back to the original adapter and the textview text came back up.
However, Here is the activity layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" >
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:textIsSelectable="false"
android:textSize="20sp"
android:paddingLeft="5dp" />
<ToggleButton
android:id="#+id/alarm_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:clickable="true"
android:onClick="enableAlarm"
android:background="?android:attr/selectableItemBackground"
android:focusable="false" />
<TextView
android:layout_width="1px"
android:layout_height="fill_parent"
android:layout_toLeftOf="#id/alarm_status"
android:layout_centerVertical="true"
android:background="?android:attr/dividerVertical" />
</RelativeLayout>
Where you are setting the text to TextView ? TextView seems to be empty. That's why it is not displaying i guess.
Either set the text to TextView in Xml file itself
android:text ="text"
or else inside getView function
TextView textView = (TextView) v.findViewById(R.id.time);
textView.setText("Text");
Too long to write in a comment, I try it as an answer. I am not sure you are getting the context correctly. Personally in a custom adapter I declare the layout inflater as follow :
private LayoutInflater mInflater = (LayoutInflater)
getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
then I use the inflater in the getView() as follow
v = mInflater.inflate(R.layout.activity_alarm_item, parent, false);
Tell me if it solves your problem orelse I remove my answer.
I am trying to create a nice layout for my list items, but my code only works when it is simplified like this:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
When I add a little bit more it compiles and runs but it force closes on start and gives me the error ArrayAdapter requires ID to be a TextView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ImageView
android:id="#+id/icon1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="#id/icon1"
android:ellipsize="marquee"
android:singleLine="true"
android:text="Some more information" />
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#id/secondLine"
android:layout_alignParentTop="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="#id/icon1"
android:gravity="center_vertical"
android:text="Some Information" />
<ImageView
android:id="#+id/icon2"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
and
public class FirstLoginActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] testcontacts = getResources().getStringArray(
R.array.testcontacts_array);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_items,
testcontacts));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(),
((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
}
I am pretty sure I'm doing this right, I've been through numerous tutorials and I've found that the fastest and most efficient way is to create a static ViewHolder class. One of the tutorials tried accessing the data directly which is what I was trying to do. I'm still a little confused on how to do so.
public class FirstLoginActivity extends ListActivity {
Context mContext;
List mList;
String[] testcontacts = getResources().getStringArray(
R.array.testcontacts_array);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_items,
testcontacts));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(),
((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
}
public View getView(int position, View convertview, ViewGroup parent) {
ViewHolder holder;
View v = convertview;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) LayoutInflater
.from(mContext);
v = inflater.inflate(R.layout.list_items, null);
holder = new ViewHolder();
holder.firstLine = (TextView) v.findViewById(R.id.firstLine);
holder.secondLine = (TextView) v.findViewById(R.id.secondLine);
holder.icon1 = (ImageView) v.findViewById(R.id.icon1);
holder.icon2 = (ImageView) v.findViewById(R.id.icon2);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.firstLine.setText(testcontacts[position]);
holder.secondLine.setText(testcontacts[position]);
// holder.icon1.setImageBitmap((position & 1) == 1 ? mIcon1: mIcon2);
//call the images directly?
return v;
}
static class ViewHolder {
TextView firstLine;
TextView secondLine;
ImageView icon1;
ImageView icon2;
}
}
You are probably using something like this (here the doc):
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.layout_1, values);
in that case your layout must be a simple layout with a TextView.
If you wanna use your own layout you need to write a custom adapter.
Build your own ArrayAdapter, then you can make the layout work however you would like.
The ArrayAdapter requires the resource ID to be a TextView XML exception means you don't supply what the ArrayAdapter expects. When you use this constructor:
new ArrayAdapter<String>(this, R.layout.a_layout_file, this.file)
R.Layout.a_layout_file 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!), something like this:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
// other attributes of the TextView
/>
If you want your list row layout to be something a little different then a simple TextView widget use this constructor:
new ArrayAdapter<String>(this, R.layout.a_layout_file,
R.id.the_id_of_a_textview_from_the_layout, this.file)
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.
You seem to be on the right lines. I'm not sure the exact issue with your code as I've not compared closely, but it works in this example.
The full tutorial is here: Android tutorial for beginners - 97 - ListView with Custom Layout
This avoids the error ArrayAdapter requires ID to be a TextView which I was also getting.
i have to make a listview that haves a list of names, and also, aligned to the left, but in the same field, the sex of the person, male or female
is possible to do it? how?
code examples welcome
EDIT
I try with the first user answer, and i got this exception: 12-14 22:39:56.191: ERROR/AndroidRuntime(917): java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
this is the code of the XML item i make:
<?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="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Left side"
android:layout_alignParentLeft="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right side"
android:layout_alignParentRight="true"/>
</RelativeLayout>
and this is the code where i have my list:
public class PendingInvitations extends ListActivity {
......
.....
....
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
private List<String> usernames=new ArrayList<String>();
for (int i=0;i<friends.size();i++)
{
usernames.add(i,friends.get(i).getFullName());
}
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item2, usernames));
this would be the view that is used for each cell
<?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="wrap_content" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Left side" android:layout_alignParentLeft="true"/>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Right side" android:layout_alignParentRight="true"/>
</RelativeLayout>
this is an example since i have no idea where your knowledge is at with lists, if the above xml was called "temp.xml" you would use this in the setlistadapter function
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class FooList extends ListActivity extends BaseAdapter {
String[] listItems = {"item 1", "item 2 ", "list", "android", "item 3", "foobar", "bar", };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_with_listview);
// implement your own adapter
}
}
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there is no need
// to reinflate it. We only inflate a new View when the convertView supplied
// by ListView is null.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.temp, null);
// Creates a ViewHolder and store references to the two children views
// we want to bind data to.
holder = new ViewHolder();
holder.left = (TextView) convertView.findViewById(R.id.left);
holder.right = (TextView) convertView.findViewById(R.id.right);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.left.setText("left text");
holder.right.setText("right text");
return convertView;
}
class ViewHolder
{
public TextView left;
public TextView right;
}
Each item of a ListView has to be a View. This includes ViewGroups. So you can use any Layout to arrange several Views inside a ListView item.