ImageView in a List Null Pointer Exception - java

I am trying to set up an list view with only some images, ie no text. Here are my files:
//the Main File:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview1 = (ListView)findViewById(R.id.listView1);
final Integer[] mThumbIds = {
R.drawable.blue, R.drawable.blue2,
R.drawable.blue3, R.drawable.blue4,
R.drawable.blue5, R.drawable.blue6
};
listview1.setAdapter(new ImageAdapter(this,mThumbIds));
listview1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
//Upon Clicking
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class ImageAdapter extends ArrayAdapter<Integer> {
private Context mContext;
Integer [] resources;
public ImageAdapter (Context c, Integer[] resources) {
super(c, R.layout.activity_main, resources);
//System.out.println("Set up of Image Adapter");
mContext = c;
this.resources=resources;
for(Integer resource:resources){
System.out.println(resource);
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.activity_main, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.layout.image_view);
imageView.setImageResource(resources[position]);
return rowView;
}
}
}
The XML is as follows:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/export_folder_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Formation Name:"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ListView
android:id="#+id/listView1"
android:layout_below="#+id/color_textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:background="#ff000000" >
</ListView>
</RelativeLayout>
And finally, the one defining the ImageView:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="64dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="9dp"
android:layout_alignParentTop="true"/>
</RelativeLayout>
Unfortunately, I get NullPointerExceptions at the point where I set the image Resource on the image view. The image resources exist- I've made sure.
I am not sure what I am doing wrong, and I am new to Android. Thank you.

Looks like you are inflating a wrong xml in your getView(),
View rowView = inflater.inflate(R.layout.activity_main, parent, false);
Here R.layout.activity_main should be replaced by the xml file which contains the ImageView.
And from your code, I think the name of the xml file containing the ImageView is, R.layout.image_view
So, your final code should be something like this,
View rowView = inflater.inflate(R.layout.image_view, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.id.imageView);
imageView.setImageResource(resources[position]);

Try the following code link :-
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(rowResourceId, parent, false);
ImageView imageView = (ImageView) rowView.findViewById(R.id.imageView);
int id = Integer.parseInt(Ids[position]);
String imageFile = Model.GetbyId(id).IconFile;
// get input stream
InputStream ims = null;
try {
ims = context.getAssets().open(imageFile);
} catch (IOException e) {
e.printStackTrace();
}
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
imageView.setImageDrawable(d);
return rowView;
}
}

Use R.id.image_view instead of using R.layout.image_view
Change Line
ImageView imageView = (ImageView) rowView.findViewById(R.layout.image_view);
To Below Line
ImageView imageView = (ImageView) rowView.findViewById(R.id.image_view);

Related

button.OnClick code runs but doesn't execute changes?

I'm trying to make an OnClick listener for an imagebutton, that is supposed to remove a bitmap (set it to null) on click. However, nothing happens when I press the button, except it does print my "Log.d()" message, and the bitmap IS actually null after the click, however changes doesn't show. The code is written inside my adapter. I even tried inserting it inside a runOnUIThread to see if that makes a difference, however there's no change.
I also tried setImageDrawable(null) and setImageResource(0) with no luck. I even tried changing other UI elements, and that doesn't work either. Only thing I can make it do is print the log message...
Here's my getView with my onClick method:
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_create_product_gridview_normal, parent, false);
//Set up viewholder
viewHolder = new ViewHolder();
viewHolder.productImageIv = (ImageView) convertView.findViewById(R.id.android_gridview_image);
viewHolder.addImageIb = (ImageButton) convertView.findViewById(R.id.addImageButton);
viewHolder.removeImageIb = (ImageButton) convertView.findViewById(R.id.removeImageButton);
viewHolder.productImageIv.setImageBitmap(images[position]);
checkForNullImages(viewHolder, position);
//Store the holder with the view
convertView.setTag(viewHolder);
viewHolder.removeImageIb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runOnUiThread (new Thread(new Runnable() {
public void run() {
images[position] = null;
viewHolder.productImageIv.setImageBitmap(images[position]);
notifyDataSetChanged();
//Does print this message, item is null, but image is still shown
Log.e("LogMSG", "item should be null " + getItem(position));
}
}));
}
});
}
return convertView;
}
And if relevant, here's my corresponding XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="#+id/android_custom_gridview_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
app:cardCornerRadius="10dp"
app:cardBackgroundColor="#color/white">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
app:cardCornerRadius="10dp">
<ImageView
android:id="#+id/android_gridview_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/gradient_background"
android:scaleType="centerCrop" />
</android.support.v7.widget.CardView>
</android.support.v7.widget.CardView>
<ImageButton
android:id="#+id/addImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-30dp"
android:elevation="#dimen/standard_12"
android:background="#drawable/icon_add" />
<ImageButton
android:id="#+id/removeImageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-30dp"
android:background="#drawable/icon_remove"
android:elevation="#dimen/standard_12" />
This is because your row view recycling is incorrect. You're not recycling the view with the following code:
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
// ...
}
return convertView;
}
because you're not using the previous convertView if it's not null.
So, change your code to something like this:
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.item_create_product_gridview_normal, parent, false);
//Set up viewholder
holder = new ViewHolder();
holder.productImageIv = (ImageView) convertView.findViewById(R.id.android_gridview_image);
holder.addImageIb = (ImageButton) convertView.findViewById(R.id.addImageButton);
holder.removeImageIb = (ImageButton) convertView.findViewById(R.id.removeImageButton);
// set click listener here.
// don't use runOnUiThread for click listener.
// bind the view here.
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// set the value for view here
holder.productImageIv.setImageBitmap(images[position]);
return convertView;
}

Android TextView SetText null object reference error

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;
}

Can't set background color for GridView layouts

I've never worked with GridView on Android. I try to inflate my layout in a GridView, and i want to have different background for every layout. I can't set background color for each layout separately, everytime i get gray color for all layouts.
My XML code :
<RelativeLayout
android:layout_width="200dp"
android:layout_height="150dp"
android:id="#+id/back">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="#+id/imageView"
android:layout_marginTop="10dp"
android:src="#drawable/splashscreen"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Science"
android:textSize="15sp"
android:layout_marginTop="10dp"
android:id="#+id/categoryTextView"
android:layout_below="#+id/imageView"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Grid adapter :
public class CellAdapter extends BaseAdapter {
private Context context;
private LinkedList<CellGrid> list;
public CellAdapter(Context context, LinkedList<CellGrid> list){
this.context = context;
this.list = list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(
R.layout.grid_cell_layout, null);
}
convertView.setBackgroundColor(list.get(position).getBackground());
TextView categoryTextView = (TextView)convertView.findViewById(R.id.categoryTextView);
ImageView imageView = (ImageView)convertView.findViewById(R.id.imageView);
categoryTextView.setText(list.get(position).getText());
imageView.setImageResource(list.get(position).getImageId());
RelativeLayout relativeLayout = (RelativeLayout) convertView.findViewById(R.id.back);
Log.d("COLOR", Integer.toString(list.get(position).getBackground()));
return convertView;
}
}
If any specific color is not satisfied then you can set random bg to every view as :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// generate the random integers for r, g and b value
int r = rand.nextInt(255);
int g = rand.nextInt(255);
int b = rand.nextInt(255);
int randomColor = Color.rgb(r,g,b);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(
R.layout.grid_cell_layout, null);
convertView.setBackgroundColor(randomColor);
}
Please try following code it helpful for you.
Replace your adapter code with following code
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = (View) inflater.inflate(
R.layout.grid_cell_layout, null);
}
Random rnd = new Random();
int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
convertView.setBackgroundColor(color);
TextView categoryTextView = (TextView)convertView.findViewById(R.id.categoryTextView);
ImageView imageView = (ImageView)convertView.findViewById(R.id.imageView);
categoryTextView.setText(list.get(position).getText());
imageView.setImageResource(list.get(position).getImageId());
RelativeLayout relativeLayout = (RelativeLayout) convertView.findViewById(R.id.back);
Log.d("COLOR", Integer.toString(list.get(position).getBackground()));
return convertView;
}
}
Feel free for comment if you have any issue
Use resources().getColor() to get color from list and set it as background
relativelayout.setBackgroundColor(getResources().getColor(list.get(position).getBackground()));
Here is my sample code..
**<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:orientation="vertical"
android:background="#color/dark_gray" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:background="#android:color/transparent"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:text="TextView"
android:textColor="#android:color/black"
android:textSize="13dp" />
**
Do you set color (AARRGGBB int value) or color resource (R.color.*)?
convertView.setBackgroundColor(list.get(position).getBackground());
There should be color in AARRGGBB format.
To get value from resources use:
context.getResources().getColor(R.color.your_color);

onclick Listener for custom listview

I am developing an android application with a custom list view ( with a single image and two text views)
The class mainactivity has ....
public class MainActivity extends ActionBarActivity {
String[] memetitles;
String[] memedesc;
ListView list;
int[] images = {R.drawable.angry_icon,R.drawable.happy_icon,R.drawable.kid_icon,R.drawable.scare_icon,R.drawable.warn_icon};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
memetitles = res.getStringArray(R.array.titles);
memedesc = res.getStringArray(R.array.notneed);
list = (ListView) findViewById(R.id.listView1);
Itarray adapter = new Itarray(this,memetitles,memedesc,images);
list.setAdapter(adapter);
setTitle("Tamil Memer");
}
The class for combining two layouts into a single list view has
class Itarray extends ArrayAdapter<String>{
Context context;
int[] image;
String[] tit1;
String[] tit2;
Itarray(Context c , String[] titles ,String[] notneed, int imgs[])
{
super(c , R.layout.single_row,titles);
this.context = c;
this.image = imgs;
this.tit1 = titles;
this.tit2 = notneed;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
if(row == null)
{
LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inf.inflate(R.layout.single_row , parent , false);
}
ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);
TextView tit = (TextView) row.findViewById(R.id.textView1);
TextView des = (TextView) row.findViewById(R.id.textView2);
myImage.setImageResource(image[position]);
tit.setText(tit1[position]);
des.setText(tit2[position]);
return row;
}
}
The two layout files :
(the one with the image and the textviews)
<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:gravity="top"
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.itassistors.tmg.MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_toEndOf="#+id/imageView1"
android:layout_toRightOf="#+id/imageView1"
android:text="#string/simple"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView1"
android:layout_alignLeft="#+id/textView1"
android:layout_alignStart="#+id/textView1"
android:text="#string/simple"
android:textAppearance="?android:attr/textAppearanceSmall" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_alignTop="#+id/textView1"
android:src="#drawable/happy_icon" />
(the one with the listview)
<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:gravity="center_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.itassistors.tmg.MainActivity" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" >
</ListView>
I want to know how and where to place the onClickListener() for this custom list view
Thanks in advance
You have two options:
1) Set the click listener in your activity:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
// Do your stuff here
}
});
2) Set the click listener in your adapter:
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
if(row == null)
{
LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inf.inflate(R.layout.single_row , parent , false);
}
ImageView myImage = (ImageView) row.findViewById(R.id.imageView1);
TextView tit = (TextView) row.findViewById(R.id.textView1);
TextView des = (TextView) row.findViewById(R.id.textView2);
myImage.setImageResource(image[position]);
tit.setText(tit1[position]);
des.setText(tit2[position]);
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Do your stuff here
}
});
return row;
}
If you are doing it in adapter you will to follow this code:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewHolderItem holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.your_list_item, null);
View row = convertView;
holder = new ViewHolderItem();
convertView.setTag(holder);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v(LOG_TAG, "ROW PRESSED");
context.startActivity(new Intent(context, YourAction.class));
}
});
} else {
holder = (ViewHolderItem) convertView.getTag();
}
return convertView;
}

Why getView() its called again for each row shown in a ListVIew when onItemClick() is invoked?

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.

Categories