I am doing project in Android. I want to change background color as well as textcolor of selected item from ListView. Here is my code
<?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:gravity="right"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ListView
android:id="#+id/listView1"
android:layout_width="265dp"
android:layout_height="366dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:layout_weight="0.00"
android:drawSelectorOnTop="true" >
</ListView>
</LinearLayout>
</LinearLayout>
So,I have ListView with some student names and with facility of multiple choice by using checkbox.
ListView stud_lst=(ListView) findViewById(R.id.listView1);
stud_lst.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
I want to change the background and text color of selected student.
I already saw some answers but I am not getting it.
Please help me.
Use a custom adapter and in your activity class do the following:
// mListview is ur listview object.
mListview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
view.setBackgroundColor("your bg's color id");
}
}
You have to create a Custom Adapter to change the item's Background Color. Here is the example of Custom adapter:
public class PaListAdapter extends BaseAdapter{
private LayoutInflater mInflater;
private ArrayList<String> platevalue = new ArrayList<String>();
ViewHolder holder;
public PaListAdapter(Context context,ArrayList<String> value)
{
// Cache the LayoutInflate to avoid asking for a new one each time.
mInflater = LayoutInflater.from(context);
//mycontext = context;
platevalue.clear();
platevalue =value;
}
public int getCount()
{
return platevalue.size();
}
public Object getItem(int position)
{
return position;
}
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.select_dialog, null);
holder = new ViewHolder();
holder.hTransID =(TextView) convertView.findViewById(R.id.txtChoice);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.hTransID.setText(platevalue.get(position));
return convertView;
}
static class ViewHolder
{
TextView hTransID;
}
}
select_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:descendantFocusability="blocksDescendants"
android:background="#000000"
>
<TextView
android:id="#+id/txtChoice"
android:layout_gravity="center_vertical|left"
android:gravity="center_vertical|left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"/>
</LinearLayout>
In Activity Class.Define it like:
simpleefficientadapter efficientadapter;
efficientadapter=new simpleefficientadapter(CLASSNAME.this, VALUES);
listView.setAdapter(efficientadapter);
Related
Hi everyone I'm trying to show with a GridView some items that show the contents of an array of strings. This is the CardView I want to set as item:
So when I click on a button, the layout of the choice of the type of film becomes visible and I set an adapter:
cTBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
postaCardVIew.setVisibility(View.GONE);
cT.setVisibility(View.VISIBLE);
GridView simpleGridView = findViewById(R.id.simpleGridView);
String genrelist[] = {"Commedia", "Animazione", "Anime", "Avventura", "Azione", "Biografico", "Documentario", "Drammatico", "Fantascienza","Fantasy",
"Guerra", "Horror", "Musical", "Storico", "Thriller", "Western", "Giallo", "Sentimentale",
};
final ArrayAdapter<String> adapter = new ArrayAdapter<String> (posta.this,android.R.layout.simple_list_item_1, genrelist);
simpleGridView.setAdapter(adapter);
}
But this is what I am getting:
I want to inflate this layout though:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="150dp"
android:layout_height="150dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="30dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Type"
android:layout_centerInParent="true"
android:textSize="20dp"
android:textStyle="bold"
/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
To get such a thing:
Can anyone help me figure out how I could inflate the desired layout?
In order to use a custom item layout, you need to create a custom adapter that extends from the BaseAdapter or ArrayAdapter
Then inflate and build your item layout in the getView() method:
public class CustomAdapter extends BaseAdapter {
String genrelist[] = {"Commedia", "Animazione", "Anime", "Avventura", "Azione", "Biografico", "Documentario", "Drammatico", "Fantascienza", "Fantasy",
"Guerra", "Horror", "Musical", "Storico", "Thriller", "Western", "Giallo", "Sentimentale",
};
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.title = convertView.findViewById(R.id.type);
holder.title.setText(genrelist[position]);
return convertView;
}
static class ViewHolder {
TextView title;
}
public int getCount() {
return genrelist.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
}
And use it as the GridView adapter:
cTBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
postaCardVIew.setVisibility(View.GONE);
cT.setVisibility(View.VISIBLE);
GridView simpleGridView = findViewById(R.id.simpleGridView);
simpleGridView.setAdapter(new CustomAdapter());
}
});
I had to manipulate the margin and cared width and wrap the CardView with a FrameLayout in order to force the margin among cards:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:layout_marginVertical="4dp">
<androidx.cardview.widget.CardView xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="120dp"
android:layout_height="120dp"
app:cardCornerRadius="30dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Type: 1"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>
Result:
I'm trying to make to-do list app. the design here "https://i.ibb.co/cXnQ9dP/Capture.png"
I got box and text code from "https://www.vogella.com/tutorials/AndroidListView/article.html" proj (15.1. Interaction between the model and Listview) but I put the XML code into my existing XML activity [not in a new activity] and changed activity name in super(context, R.layout.rowbuttonlayout, list); and view = inflator.inflate(R.layout.rowbuttonlayout, null); to my main activity name
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mando.todolist.new_list">
.............background and buttons code here............
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="#id/plus"
android:orientation="horizontal"
android:paddingTop="205dp"
android:id="#+id/repeat_layout"
>
<CheckBox
android:id="#+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4px"
android:layout_marginRight="10px" >
</CheckBox>
<TextView
android:id="#+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#+id/label"
android:textSize="50px"
android:layout_alignRight="#id/check"
>
</TextView>
</LinearLayout>
public InteractiveArrayAdapter(Activity context, List<Model> list) {
super(context, R.layout.activity_new_list, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected CheckBox checkbox;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.activity_new_list.,null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
}
}
public class new_list extends ListActivity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// create an array of Strings, that will be put to our ListActivity
ArrayAdapter<Model> adapter = new InteractiveArrayAdapter(this,
getModel());
setListAdapter(adapter);
}
private List<Model> getModel() {
List<Model> list = new ArrayList<Model>();
list.add(get("Linux"));
list.add(get("Windows7"));
list.add(get("Suse"));
list.add(get("Eclipse"));
list.add(get("Ubuntu"));
list.add(get("Solaris"));
list.add(get("Android"));
list.add(get("iPhone"));
// Initially select one of the items
list.get(1).setSelected(true);
return list;
}
private Model get(String s) {
return new Model(s);
}
}
The output is All activity has been duplicated [including background and buttons] instead duplicating checkbox with text only in the same activity
Move your background and buttons to the xml file where you put your ListView
it should look like this, because the item xml you are using where your CheckBox exists is the one used for the ListView, if you but the button it will duplicated too
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- background and buttons code here -->
<ListView
android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:headerDividersEnabled="true"/>
</LinearLayout>
I am new to android and I am getting a
Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
error on my app. I have read other questions on here like this one - java.lang.NullPointerException - setText on null object reference but I still get the same issue. My format is a little bit different as this is done in a Fragment and what I am doing is having a Custom Adapter from a listview. Here is my code
fragment_song_genre.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">
<data class="SongGenreBinding">
<variable
name="handler"
type="com.mgrmobi.joox.fragments.FilterSongGenreFragment" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000">
<RelativeLayout
android:id="#+id/toprow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:background="#null"
android:onClick="#{ handler.onCloseClicked }"
android:src="#drawable/search_close" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="80dp"
android:text="Genre"
android:textColor="#fff"
android:textSize="20sp" />
<TextView
android:onClick="#{ handler.reset }"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:text="#string/reset"
android:textAllCaps="true"
android:textColor="#fff"
android:textSize="12sp" />
</RelativeLayout>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toprow"
android:layout_marginTop="24dp"></ListView>
</RelativeLayout>
That is the main page and it has a Listview in the Bottom and here is the fragment that calls that xml layout
public class FilterSongGenreFragment extends BaseFragment {
private SongGenreBinding binding;
private ArrayList<String> genres;
String[] names= {"Johm","Paul","Mike"};
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
}
private static final String GENRES_KEY = "genres";
public static FilterSongGenreFragment newInstance(ArrayList<String> genres) {
Bundle args = new Bundle();
args.putStringArrayList(GENRES_KEY, genres);
FilterSongGenreFragment fragment = new FilterSongGenreFragment();
fragment.setArguments(args);
return fragment;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_song_genre, container, false);
binding.setHandler(this);
genres = getArguments().getStringArrayList(GENRES_KEY);
initList();
return binding.getRoot();
}
private void initList() {
// ArrayAdapter adapter = new ArrayAdapter(getActivity(), R.layout.genre_list_text, android.R.id.text1, genres);
FilterSongsAdapter filterSongsAdapter= new FilterSongsAdapter(getActivity(),names);
binding.list.setAdapter(filterSongsAdapter);
binding.list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view,int position, long l) {
((SongFilterListener) getActivity()).onGenreSelected(genres.get(position));
/*
textView = (ImageView) view.findViewById(R.id.selected_genre);
textView.setVisibility(View.VISIBLE);
*/
// close();
}
});
}
private void close() {
getActivity().getFragmentManager().beginTransaction().remove(this).commit();
}
public void onCloseClicked(View view) {
close();
}
public void reset(View view) {
((SongFilterListener) getActivity()).onResetFilters();
close();
}
}
Here is the xml for the listview custom style genre_list_text.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="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|left"
android:text="Genre"
android:paddingBottom="16dp"
android:paddingLeft="4dp"
android:paddingTop="16dp"
android:textColor="#fff"
android:textSize="16sp" />
<ImageView
android:id="#+id/selected_genre"
android:layout_height="24dp"
android:layout_width="24dp"
android:visibility="invisible"
android:src="#drawable/check_circle"
android:layout_marginStart="140dp"
android:layout_centerVertical="true" />
</RelativeLayout>
and here is my adapter and as stated before the error happens in the SetText area
public class FilterSongsAdapter extends ArrayAdapter<String> {
private Context c;
String[] names= {};
LayoutInflater inflater;
public FilterSongsAdapter(Context context,String[] names) {
super(context,R.layout.genre_list_text,names);
this.c=context;
this.names=names;
}
public static class ViewHolder {
TextView text1;
}
#Override
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
holder = new ViewHolder();
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.from(c).inflate(R.layout.genre_list_text, null);
// Initialize
holder.text1=(TextView) convertView.findViewById(R.id.text1);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
holder.text1.setText(names[position]);
return convertView;
}
}
The SetText inside the GetView is throwing the exception every time, that TextView should have 3 objects names from the Names String Array which I have seen that it has. Based on the error I know that i'm setting the SetText before the FindByID method locates the TextView but I have moved things around and nothing works. Any help would be great . I also been following this tutorial for reference https://www.youtube.com/watch?v=99C_UpLcBRk . I do not know if maybe with a Fragment things are different.
in your layout you have given default id to TextView android:id="#android:id/text1".
and in JAVA file you are giving R.id.text1
make changes in xml or java.
ether change in xml from android:id="#android:id/text1" to android:id="#+id/text1"
or in java android.R.id.text1
#Override
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder = new ViewHolder(); //because error says null object reference, it means object of TextView `text1` is not found.
inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView==null){
convertView = inflater.inflate(R.layout.genre_list_text, null);
holder.text1=(TextView) convertView.findViewById(R.id.text1);
holder.text1.setText(names[position]);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
And from your provided XML code, I can see you did not provided a proper id for TextView. Change in XML from android:id="#android:id/text1" to android:id="#+id/text1".
In your genre_list_text.xml change android:id="#android:id/text1" to android:id="#+id/text1"
and in your getView Method
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.genre_list_text, parent, false);
viewHolder = new ViewHolder();
holder.text1=(TextView) view.findViewById(R.id.text1);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
holder.text1.setText(names[position]);
return view;
}
Hoping someone can help. I'm having an issue it seems inflating my view. My goal is to display a list of items in a custom layout using a custom array adapter. I re-worked some of my original code using another SO post, but where my simple adapter worked fine, the new list doesn't display. Please see below:
This is my Fragment class.
HomeFeedFragment.java
public class HomeFeedFragment extends ListFragment {
private ListView listView;
private ArrayList<MainEvent> items;
private MainEventListViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_homefeed,
container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//GetEvents is just a test method to return a list of pre-filled event objects
items = GlobalList.GetEvents();
adapter = new MainEventListViewAdapter(getActivity(), android.R.id.list, items);
listView.setAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// do something with the data
}
}
My custom row layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<!-- ListRow Left sied Thumbnail image -->
<LinearLayout
android:id="#+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip"
android:padding="3dip" >
<ImageView
android:id="#+id/list_image"
android:layout_width="50dip"
android:layout_height="50dip" />
</LinearLayout>
<!-- Heading Text -->
<TextView
android:id="#+id/eventheader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/thumbnail"
android:layout_toRightOf="#+id/thumbnail"
android:textColor="#040404"
android:textSize="15sp"
android:textStyle="bold"
android:typeface="sans" />
<!-- Event Description -->
<TextView
android:id="#+id/eventdescription"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/thumbnail"
android:layout_below="#id/eventheader"
android:layout_marginTop="1dip"
android:layout_toRightOf="#+id/thumbnail"
android:textColor="#343434"
android:textSize="10sp"
tools:ignore="SmallSp" />
<!-- Posted Time -->
<TextView
android:id="#+id/eventpostedtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#id/eventheader"
android:layout_marginRight="5dip"
android:gravity="right"
android:textColor="#10bcc9"
android:textSize="10sp"
android:textStyle="bold"
tools:ignore="SmallSp" />
</RelativeLayout>
The actual fragment layout:
<?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" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
And my custom ArrayAdapter:
public class MainEventListViewAdapter extends ArrayAdapter<MainEvent> {
private Context context;
private List<MainEvent> eventList;
public MainEventListViewAdapter(Context context, int textViewResourceId, List<MainEvent> eventList){
super(context, textViewResourceId, eventList);
this.context = context;
//this.eventList = eventList;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtEventHeader;
TextView txtEventDescription;
TextView txtEventPostedTime;
}
public int getCount(){
if(eventList!=null){
return eventList.size();
}
return 0;
}
public MainEvent getItem(int position){
if(eventList!=null){
return eventList.get(position);
}
return null;
}
public long getItemId(int position){
if(eventList!=null){
return eventList.get(position).hashCode();
}
return 0;
}
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder = null;
MainEvent rowItem = getItem(position);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(convertView==null){
convertView = inflater.inflate(R.layout.fragment_homefeed_rowlayout, parent, false);
holder = new ViewHolder();
holder.txtEventHeader = (TextView) convertView.findViewById(R.id.eventheader);
holder.txtEventDescription = (TextView) convertView.findViewById(R.id.eventdescription);
holder.txtEventPostedTime = (TextView) convertView.findViewById(R.id.eventpostedtime);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.txtEventHeader.setText(rowItem.getHeadline());
holder.txtEventDescription.setText(rowItem.getDescription());
holder.txtEventPostedTime.setText(rowItem.getPostedTime());
/*TextView text = (TextView) v.findViewById(R.id.label);
text.setText(m.getHeadline());
ImageView imageView = (ImageView) v.findViewById(R.id.icon);
imageView.setTag(m.getImageURL());
//DownloadImageTask dt = new DownloadImageTask();
dt.execute(imageView);
return v;*/
return convertView;
}
public List<MainEvent> getEventList(){
return eventList;
}
public void setEventList(List<MainEvent> eventList){
this.eventList = eventList;
}
}
^ I initially had an Async Task in this class to retrieve images for each item, but I've removed all of that for now.
I don't get any actual errors in LogCat, no crashes or anything, the View just isn't inflating. Any help is appreciated.
Well this is embarrassing. I found out the issue. Apparently, I forgot to uncomment the line in the adapter constructor that initializes the event list:
//this.eventList = eventList;
I'd commented it out temporarily to fix another bug. Working fine now, but thanks for your suggestion.
Why everytime the onItemClick() event is invoked on a ListView with a custom adapter, the getView() method in the adapter is called again?
I have the following code in API level 7, and when I try to change the checked value in the row's CheckedTextView object (stored in a ViewHolder), the adapter's getView() for each row is invoked and I got a strange behaviour(The selected row in the listView check/uncheck the CheckedTextView in another row) :
The code for the Activity is:
public class EnvioImagenesActivity extends Activity implements OnItemClickListener {
ListView listView;
private EnvioImagenAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.envio_imagenes);
listView=(ListView) findViewById(R.id.listViewEnvios);
adapter=new EnvioImagenAdapter(this,Store.getImages());
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
}
public void onItemClick(AdapterView<?> arg0, View view, int pos,
long id) {
ViewHolder holder=(ViewHolder) view.getTag();
holder.checkedTextView.toggle();
}
}
The code for the Xml layout activity is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/envioImagenes"
android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center"/>
<ListView
android:id="#+id/listViewEnvios"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:choiceMode="multipleChoice">
</ListView>
</LinearLayout>
The listview adapter:
public class EnvioImagenAdapter extends BaseAdapter {
private List<ImageUri> items;
private Context context;
public EnvioImagenAdapter(Context context, List<ImageUri> items) {
this.context=context;
this.items = items;
}
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("---getView() method called");
View v = convertView;
ViewHolder holder;
if (v == null) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row_envio_imagen, null);
holder = new ViewHolder();
holder.imageView = (ImageView) v.findViewById(R.id.imageView1);
holder.textView = (TextView) v.findViewById(R.id.textView1);
holder.temporalProgressBar = (ProgressBar) v
.findViewById(R.id.progressBar1);
holder.checkedTextView = (CheckedTextView) v
.findViewById(R.id.checkedTextView12);
holder.selected = true;
holder.position = position;
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
ImageUri imageUri = items.get(position);
File f = new File(imageUri.getImageUri().getPath());
String fileSize = Util.formatFileSize(f.length());
holder.textView.setText(fileSize);
new ImageTask(imageUri).execute(holder);
return v;
}
class ImageTask extends AsyncTask<ViewHolder, Void, Bitmap> {
public ImageTask(ImageUri imageUri) {
this.imageUri = imageUri;
}
private ImageUri imageUri;
private ViewHolder viewHolder;
#Override
protected Bitmap doInBackground(ViewHolder... params) {
viewHolder = params[0];
Bitmap bmp = BitmapFactory.decodeFile(imageUri.getThumbUri()
.getPath());
return bmp;
}
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
viewHolder.temporalProgressBar.setVisibility(View.GONE);
viewHolder.imageView.setVisibility(View.VISIBLE);
viewHolder.imageView.setImageBitmap(result);
};
}
class ViewHolder {
public int position;
CheckedTextView checkedTextView;
ProgressBar temporalProgressBar;
ImageView imageView;
TextView textView;
boolean selected;
}
}
And the xml layout for each row is:
<?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="?android:attr/listPreferredItemHeight"
android:padding="6dip" >
<ProgressBar
android:id="#+id/progressBar1"
android:layout_width="45dip"
android:layout_height="45dip"
android:layout_alignParentLeft="true" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="45dip"
android:layout_height="45dip"
android:layout_alignParentLeft="true" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dip"
android:layout_toRightOf="#id/imageView1" />
<CheckedTextView
android:id="#+id/checkedTextView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkMark="?android:attr/textCheckMark"
android:checked="true"
android:layout_alignParentRight="true">
</CheckedTextView>
<ProgressBar
android:id="#+id/progressBar2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_below="#+id/textView1"
android:layout_toLeftOf="#id/checkedTextView12"
android:layout_toRightOf="#id/imageView1"
android:paddingLeft="5dip"
android:paddingTop="2dip" />
</RelativeLayout>
And when I run the app in the simulator and make click in a row, I obtain in the LogCat:
System.out(2947): ---getView() method called
for each row displayed in the list.
Thanks in advance!!!!
I had a similar problem in the code caused
ListView.setChoiceMode (ListView.CHOICE_MODE_SINGLE);
When you click on the item for each item getview summoned again, in your case, you can try to remove android:choiceMode="multipleChoice"
Maybe this will help you.
I have noticed that accessing the views from outside the getView() rarely produces the expected behaviour. I suppose it is because of the recycling mechanism. Two alternative options work:
1) implement onClick() in getView()
2) If you want to keep your logic out of the adapter, in onItemClick(), change the underlying data and call adapter.notifyDatasetChanged(). The checkbox will toggle.