I have a list of textView that is programmed dynamically...
GridView layout = (GridView) context.findViewById(R.id.linearLayout1);
PrizeAdapter adapter = new PrizeAdapter(context, 0, 0, game.getPrizeList());
layout.setAdapter(adapter);
Adapter Class:
public class PrizeAdapter extends ArrayAdapter<String> {
private List<String> objects;
public PrizeAdapter(Context context, int resource, int textViewResourceId,
List<String> objects) {
super(context, resource, textViewResourceId, objects);
this.objects = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView text = new TextView(getContext());
text.setId(position);
text.setText(objects.get(position));
text.setTextSize(12);
text.setPadding(0, 5, 0, 5);
text.setTextColor(Color.WHITE);
text.setBackgroundColor(Color.GRAY);
text.setGravity(Gravity.CENTER | Gravity.BOTTOM);
return text;
}
}
Supposedly, I have created a 10 TextView. How can i get the particular textView so i can color it differently.
I tried this
GridView layout = (GridView) context.findViewById(R.id.linearLayout1);
TextView view = (TextView) layout.findViewById(1);
view.setBackgroundColor(Color.YELLOW);
view.setTextColor(Color.RED);
But it doesn't work and just encountered a nullpointer exception.
Please help.
The reason for such behavior is you are doing it too early.
i.e even before the view are created with id 1 you are trying to access them.
So what is happening is, you ask adapter to inflate view and adapter takes control checking what is visible and what should be displayed.
and immediately after if ( before view are populated) you call findviewbyID(1) so this view is still not created hence you get null pointer.
The code will work if we try to use a button to do the task after grid is populated.
final GridView layout = (GridView) findViewById(R.id.linearLayout1);
PrizeAdapter adapter = new PrizeAdapter(this, 0, 0, objects2);
layout.setAdapter(adapter);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
TextView view = (TextView) layout.findViewById(1);
view.setBackgroundColor(Color.YELLOW);
view.setTextColor(Color.RED);
// TODO Auto-generated method stub
}
});
So 2 solution
1) delayed handler post for changing color.
2) create a custom callback interface which will give you back result like view 1 loaded.
Use ViewGroup.getChildAt(position), which will return you the view at that position. Then Typecast it to TextView(as you are setting the TextView as direct item View) to set color.
One more thing you cannot use findViewById() when you are creating objects dynamically unless you set ID for the object.
Related
In my program, I have a Fragment which dynamically adds custom items to a ListView. These items each have 2 Buttons, which are supposed to have a certain functionality (like removing the specific item from the list). I would like to set an OnClickListener for them, calling a function within my Fragment Class.
Simple xml onClick attributes cannot find the function and when I try to add the onClickListener within the onCreateView() method (like with Listeners for static Buttons). But when the fragment is created, a NullPointerException is called, because the referenced Buttons are not part of the Fragment (?).
How can I call a function from my Fragment after pressing a dynamically added Button (or Checkbox)?
this is easier if you post some code
In my code I have something similar, I have one listview with a Array Adapter, and in some line I have one imageButton with a funtion.
I solve my problem with a class to work on my adapter and in that that I apply the functionaly to the Button.
Main_Class code :
ListViewResources listViewResources = new ListViewResources(this, resourcesName);
listView = (ListView) popupView.findViewById(R.id.listView1);
listView.setAdapter(listViewResources);
ListViewResouces_Class:
public class ListViewResources extends ArrayAdapter<String>{
Activity context;
String[] resourcesName;
public ListViewResources(Activity context, String[] resourcesName) {
super(context, R.layout.popup_listitem_resources, resourcesName);
this.context = context;
this.resourcesName = resourcesName;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.popup_listitem_resources, null, true);
TextView resourceName = (TextView)rowView.findViewById(R.id.textViewResourceName);
ImageView openResource = (ImageView)rowView.findViewById(R.id.buttonOpenResource);
openResource.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//code for happen on Button Click
}
});
resourceName.setText(resourcesName[position]);
return rowView;
}
Overview:
I have a ListView with a custom adapter/layout, every time a user adds a new row (which contains a number), I check if that number is the smallest in the list. If so, an image within that row must be set as visible while setting all other row's images as invisible.
Problem:
My ListView does not set any row's image as visible, even though I have the index of the smallest element.
How I'm doing it:
//In MainActivity
private void addProduct(float price) { //User adds product
priceList.add(price); //Add to Float list
adapter.notifyDataSetChanged();
updateView(findMinIndex(priceList)); //Find smallest val indx
}
private void updateView(int index){
View v = listView.getChildAt(index -
listView.getFirstVisiblePosition());
if(v == null)
return;
ImageView checkMark = (ImageView) v.findViewById(R.id.check_mark);
checkMark.setVisibility(View.VISIBLE); //Initially set Invisible
}
Edit, CustomAdapter:
public CustomList(Activity context,
ArrayList<Float> priceList) {
super(context, R.layout.list_single, priceList);
this.context = context;
priceList = priceList;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.list_single, null, true);
TextView price = (TextView) rowView.findViewById(R.id.new_price);
ImageView cheapest = (ImageView) rowView.findViewById(R.id.check_mark);
price.setText(priceList.get(position) + "");
return rowView;
}
Thank you
It is your priceList binded with the adapter?
First of all i would put a breakpoint to see if you are getting the right view in the updateView method.
try this way;
Create a Pojo class with imageview and it's state(Visibility) initially set all to invisible
Add your items to the ArrayList of Pojo Class type.
when user enters a new row based on your requirement set visibility state to true or false(visible or invisible) and call notifyDataSetChanged() to the adapter.
Doing this way you can have a easy track of the items.
I got it working :).
Problem is that adapter.notifyDataSetChanged(); is async, so while it's doing that, updateView(findMinIndex(priceList)); runs but doesn't find the new row as it should. Therefore, I add a runnable to the ListView object as so:
adapter.notifyDataSetChanged();
listView.post( new Runnable() {
#Override
public void run() {
updateView(findMinIdx(priceList));
}
});
Now it works perfectly!
I am using a custom spinner library, Material Spinner. I have set adapter to the spinner as I want the font size to be different in the getDropDownView. I have three spinners out of which two just show the packagename. The middle spinner is working properly.
Everything is the same for all three spinners other than the array and the width. So why is the middle spinner. I can't figure out what the issue is.
This is not a duplicate question
One reason mentioned is that the getView method should be overridden. As can be seen below, it has been done. What I did find that in the case of the 1st and 3rd spinner the getView method or the getDropDownView method is not being called. I don't understand why.
getItemCount, getItemId, getItem methods are not needed. But when I had these methods also, the result did not change.
MaterialSpinner msDay = (MaterialSpinner) getActivity().findViewById(R.id.fgenderage_ms_day);
List dayList = Arrays.asList(getResources().getStringArray(R.array.fgenderage_day));
msDay.setItems(new EnglishSpinnerAdapter(getActivity(), dayList));
MaterialSpinner msMonth = (MaterialSpinner) getActivity().findViewById(R.id.fgenderage_ms_month);
List monthList = Arrays.asList(getResources().getStringArray(R.array.fgenderage_month));
msMonth.setAdapter(new EnglishSpinnerAdapter(getActivity(), monthList));
MaterialSpinner msYear = (MaterialSpinner) getActivity().findViewById(R.id.fgenderage_ms_year);
List yearList = Arrays.asList(getResources().getStringArray(R.array.fgenderage_year));
msYear.setItems(new EnglishSpinnerAdapter(getActivity(), yearList));
The adapter:
public class EnglishSpinnerAdapter extends MaterialSpinnerAdapter{
private List list;
private Context ctx;
public EnglishSpinnerAdapter(Context context, List items) {
super(context, items);
ctx = context;
list = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = new TextView(ctx);
textView.setText(list.get(position).toString());
return textView;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView textView = new TextView(ctx);
textView.setText(list.get(position).toString());
return textView;
}
change this
msDay.setItem(new EnglishSpinnerAdapter(getActivity(), dayList));
to this
msDay.setAdapter(new EnglishSpinnerAdapter(getActivity(), dayList));
EDIT: Sorry I realise from your comment my question was not clear enough. I will post a new one. Sorry for this and thanks for your answers
I am populating a ListView from a Json file.
With my listadapter, I can easily assign appropriate json data to each row of my list. That works well for text, for example:
TextView tv = (TextView)ll.findViewById(R.id.descView);
tv.setText(i.desc);
With the above code, every row will be correctly populated by the good json data.
However, I don't manage to do the same thing for an image. I have tried to set the right image from my json data using this:
ImageView iv = (ImageView)ll.findViewById(R.id.imgView);
iv.setBackgroundDrawable(context.getResources().getDrawable(i.img));
I guess I am doing something wrong with the type of my parameters: "setBackgroundDrawable" requires a drawable parameter.
"getDrawable" requires an int.
I have set the type of my field img to int, but that doesn't work.
Any idea why?
My list adapter:
public class adapter extends ArrayAdapter<ListItems> {
int resource;
String response;
Context context;
//Initialize adapter
public ListItemsAdapter(Context context, int resource, List<ListItems> items) {
super(context, resource, items);
this.resource=resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
//Get the current object
ListItems i = getItem(position);
//Inflate the view
if(convertView==null)
{
ll = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li;
li = (LayoutInflater)getContext().getSystemService(inflater);
li.inflate(resource, ll, true);
}
else
{
ll = (LinearLayout) convertView;
}
//For the message
TextView tv = (TextView)ll.findViewById(R.id.descView);
tv.setText(i.desc);
// For the Img
ImageView iv = (ImageView)ll.findViewById(R.id.imgView);
iv.setBackgroundDrawable(context.getResources().getDrawable(i.img));
return ll;
}
my item class:
public class ListItems{
int id;
int img;
String desc;}
And a sample of my json file:
[{"id":10001,"img":e1,"desc":"desc1"},
{"id":10002,"img":e2,"desc":"desc2"},
{"id":10003,"img":e3,"desc":"desc3"}]
Try this
iv.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.img));
or
iv.setBackgroundResource(R.drawable.img);
Now as getDrawable and setBackgroundDrawable both are depricated you should set drawable as Background like this :
view.setBackground(ContextCompat.getDrawable(this, R.drawable.your_drawable));
and if you are targating minSdk below 16 then make a check like this :
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
view.setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.your_drawable));
} else {
view.setBackground(ContextCompat.getDrawable(this, R.drawable.your_drawable));
}
If you want to change the ImageView image/src,
In Layout android:src="#drawable/img" or app:srcCompat="#drawable/img"
Programmatically imageview.setImageResource(R.drawable.img);
If you want to change the background of ImageView
In Layout android:background="#drawable/img"
programmatically selectimg.setBackgroundResource(R.drawable.circle_filled);
Here imageview is a ImageView and img is a drawable.
Here the new Method
recyclerView.setBackgroundResource(R.drawable.edit_text_button_shape);
don't use this it's an old method
recyclerView.setBackgroundDrawable(this.getResources().getDrawable(edit_text_button_shape));
I'm trying to change the item colors of a listview in android, but I can't make it work. I want the colors to alternate... I've made my own adapter and inside the getView method I changed the color before returning the list view but it doesn't work I don't know why...
Here is my code:
public class EventoAdapter extends ArrayAdapter<Evento>{
Context context;
int layoutResourceId;
ArrayList<Evento> evento = null;
public EventoAdapter(Context context, int textViewResourceId,
ArrayList<Evento> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
this.layoutResourceId = textViewResourceId;
this.context = context;
this.evento = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View row = convertView;
EventoHolder holder = null;
if(row == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new EventoHolder();
holder.nombre = (TextView)row.findViewById(R.id.nombreEvento);
holder.total = (TextView)row.findViewById(R.id.totalEvento);
holder.moneda = (TextView)row.findViewById(R.id.moneda);
holder.fecha = (TextView)row.findViewById(R.id.fecha);
row.setTag(holder);
}else{
holder = (EventoHolder)row.getTag();
}
Evento ev = evento.get(position);
holder.nombre.setText(ev.getNombre());
holder.total.setText(Integer.toString(ev.getTotal()));
holder.moneda.setText("$");
holder.fecha.setText("20/12/11");
if(position%2==0){
row.setBackgroundColor(R.color.colorPar);
}else{
row.setBackgroundColor(R.color.colorImpar);
}
return row;
}
static class EventoHolder{
TextView nombre;
TextView total;
TextView moneda;
TextView fecha;
}
}
Of course I have defined the colorPar and colorImpar inside my own colors.xml resource.
Any Idea why this is not working??
Thanks!
Looks like the default background for view is transparent. Try this and it should work..
if(position%2==0){
row.setBackgroundColor(new
ColorDrawable(context.getResources().getColor(R.color.colorPar)));
}else{
row.setBackgroundColor(new
ColorDrawable(context.getResources().getColor(R.color.colorImpar)));
}
Use setBackgroundResource() rather than setBackgroundColor().
setBackgroundResource() takes an integer resource index as parameter, and load whatever resource that index points to (for example; a drawable, a string or in your case a color).
setBackgroundColor(), however takes an integer representing a color. That is, not a color-resource, but a direct, hexadecimal, rgba value (0xAARRGGBB).
So, when you call setBackgroundColor() using a resource index (say 7f050001, which is the first color index), you always set your color to a:127 r:5 g:0 b:1.
In case you have more then just one or two properties you wish to change for an alternate or any other additional layout, the below post describes how to apply separated layouts based on the item index.
Just override the getViewTypeCount and getViewType Methods(or in Xamarin ViewTypeCount property and GetViewType Method)
links:
Android ListView with multiple layouts
https://developer.xamarin.com/api/property/Android.Widget.BaseAdapter.ViewTypeCount/