I want to open a dialog for user to choose from multiple items but I get an error when setAdapter() was going to execute...
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Dialog cd = new Dialog(Main1.this);
String[] mobileArray = {"Android","IPhone","WindowsMobile","Blackberry","WebOS","Ubuntu","Windows7","Max OS X"};
ArrayAdapter adapter = new ArrayAdapter<String>(cd.getContext(), R.layout.lvlayout, mobileArray);
ListView listView = (ListView) findViewById(R.id.listviewID);
listView.setAdapter(adapter);
cd.setContentView(R.layout.dialogLayout);
cd.setTitle("MEOW");
cd.show();
}
});
ListView is in Dialog layout. whats Wrong here?
Simply there are two mistakes in your code, you are calling this line without prefixing it with cd. so that you have to do it like this,
ListView listView = (ListView) cd.findViewById(R.id.listviewID);
Another mistake you are doing is calling findViewById before calling setContentView(), This may also raise NPE.
So I suggest you to move this up and re-arrange like this
cd.setContentView(R.layout.dialogLayout);
ListView listView = (ListView) cd.findViewById(R.id.listviewID);
The problem is that your variable listView null is when you call setAdapter() on it. So the call to findViewById() returns null. Maybe you just used a wrong ID.
Just initialize your listview outside of onClick listener.
Initializing it in onCreate() is more preferable.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
// initialize
ListView listView = (ListView) findViewById(R.id.listviewID);
}
You have some basic mistakes here.
The major mistake is calling the cd.setContentView(R.layout.dialogLayout); at the end of your code. You need to call before you want to find something in that content layout.
And the other mistake is trying to find the list. You need to get a view to find the list in that view. This might be something like this.
ListView listView = (ListView) cd.getView().findViewById(R.id.listviewID);
However, I do prefer the following solution for your problem. This might be an easier way for what you're trying to achieve.
Here's a nice example of implementing a custom dialogue. You can have a look here.
https://github.com/afollestad/material-dialogs
So, now as you're getting NullPointerException, findViewById is not returning any reference of your ListView I guess. So here by using the library mentioned above you can achieve this quite easily.
// Initialize your dialogue
MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title("MEOW")
.customView(R.layout.dialogLayout, true)
.positiveText(R.string.ok)
.negativeText(R.string.cancel)
.onNegative(new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
dialog.dismiss();
}
})
.show();
// Now get the view of that dialogue.
View view = dialog.getCustomView();
// Initialize the array adapter
String[] mobileArray = {"Android","IPhone","WindowsMobile","Blackberry","WebOS","Ubuntu","Windows7","Max OS X"};
ArrayAdapter adapter = new ArrayAdapter<String>(cd.getContext(), R.layout.lvlayout, mobileArray);
// Get the list view and set the adapter
ListView listView = (ListView) view.findViewById(R.id.listviewID);
listView.setAdapter(adapter);
Related
i've created a custom list with four textviews...the data in this list is saved through a dialog which has a ok button. when i add the data, it gets saved in the list(works fine till now). when i add the next element, all the rows gets same value as the last one...the notifyDatasetChanged() is also not working...am i wrong somewhere?...this is my code...
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String val = editquantity.getText().toString();
valq1 = Integer.parseInt(val);
ListView l;
l = (ListView) v.findViewById(R.id.order_listview);
myAdapter adapter = new myAdapter(getActivity(), row);
l.setAdapter(adapter);
row.add("");
adapter.notifyDataSetChanged();
builder.dismiss();
}
});
builder.setView(dialog);
builder.show();
You created new adapter everytime you click ok. Put your adapter code outside the onclick method:
ListView l = (ListView) v.findViewById(R.id.order_listview);
myAdapter adapter = new myAdapter(getActivity(), row);
l.setAdapter(adapter);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String val = editquantity.getText().toString();
valq1 = Integer.parseInt(val);
row.add(""); //add new item to the list
adapter.notifyDataSetChanged(); //notify adapter
builder.dismiss();
}
});
builder.setView(dialog);
builder.show();
You need to use addAll() method for adding new values remaining old values are same in arraylist.
row.addAll("test");
Why are you adding row as blank.
Secondly you have set row in adapter without defining it.
Please provide more details to the question as i cannot understand where row has been declared.
Coming to the similar value problem.
You need to update row array because it has been set on adapter.
There are three things you need to change
1. Declare your ListView object outside of the onCreate()
2. Declare your adapter object outside of the onCreate()
Now this initialization of this below line needs to be initialized only once in onCreate(). You need not to initialize it again and again when you add new item.So below line write in your onCreate().
myAdapter adapter = new myAdapter(getActivity(), row);
When you add new item you only need to add that item in your arraylist named row onClick of ok button and then call adapter.notifyDataSetChanged(); it will work fine.
I want to change the background of a TextView, which is inserted in a ListView. The ListView contains a series of TextView, and the value of each one is retrieved from a simple List. Now I show you my snippet:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.town_selection);
list = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<>(this, R.layout.string_item, App.towns);
list.setAdapter(adapter);
list.setOnItemClickListener(this);
adapter.notifyDataSetChanged();
list.invalidate();
// list.getCount() returns zero!!
// and so, list.getChildAt(...) returns null!!
}
App.towns is the list of String I was talking, and its length is greater than 0. When the app is running it seems ok, because the ListView is showing the items, but at the end of the onCreate I need to change the background color of some items, but the ListView seems not ready as I commented.
notifyDataSetChanged() and invalidate() doesn't help.
I'm not claiming that my answer is the best, but I have some idea and I'd like to share it.
If your string list of towns, as I understood, is unchangable let's do the following:
...
final Context context = this;
String [] towns = new String [] { "town_1", "town_2", "town_3" };
ListView list;
ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.town_selection);
list = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<String>(this, R.layout.string_item, R.id.string_item_text, towns)
//R.id.string_item_text - id your TextView in item of your list
{
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
TextView txtView = (TextView) v.findViewById(R.id.string_item_text);
String sText = txtView.getText().toString();
if (sText.equals("town_1")) {
txtView.setBackgroundColor(Color.parseColor("#93C47D")); //#93C47D - just example
} else if (sText.equals("town_2")){
txtView.setBackgroundColor(Color.parseColor("#6FA8DC")); //#6FA8DC - just example
} else if (sText.equals("town_3")){
txtView.setBackgroundColor(Color.parseColor("#F6B26B"));//#F6B26B - just example
}
return v;
}
};
list.setAdapter(adapter);
...
It helped me in one of Android projects. If it will help you it'll be good.
In any way, leave your feedback.
You will need to write a custom adapter for your list view and change the color when creating each item in the list view.
This SO question - Custom Adapter for List View has great answers which should help you with how to create this custom adapter. You will not be able to do it with the ArrayAdapter as-is.
The best solution is to use a custom adapter instead of ArrayAdapter , then in the getView() method of custom adapter you can change the color of the textview
If, for some reason, you need to change your background is TextViev, the information about it should be somewhere to store and change the background is using methods in your custom adapter. Create your own custom adapter.
I have an AlertDialog with a ListView set to multiple selection on it. It also has a Button on it.
The Button open another AlertDialog that if ok'ed will remove the selected items from the data set of the ListView, and then tell the adapter of the list view that the dataset has changed with the notifyDataSetChanged() method.
This all works fine except for one thing. The ListView does not update it's content until I interact with something. Then it updates to the correct data.
This is not a big problem, but I really would like the ListView to appear correct at once, and not just after the focus has changed.
Code:
Button remove = (Button) view.findViewById(R.id.btn_remove_questions_edit_rack);
final Context con = this;
remove.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Builder warnBuild = new Builder(con);
warnBuild.setMessage(R.string.question_deletion_warning);
warnBuild.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
SparseBooleanArray checked = list.getCheckedItemPositions();
for (String s : keys)
{
int i = keys.indexOf(s);
if (checked.get(i))
{
toRemove.add(map.get(s));
map.remove(s);
}
}
keys.clear();
keys.addAll(map.keySet());
((ArrayAdapter) list.getAdapter()).notifyDataSetChanged();
list.clearChoices(); //This makes sure the selection is cleared, if it isn't, some of the other items (those that now has the index of the selected items) will be selected when the View refreshes.
dialog.dismiss();
}
});
//Negative button here, not relevant.
}
});
Where map and keys are:
final HashMap<String, QualityQuestion> map = new HashMap<>();
//I add items to the map
final ArrayList<String> keys = new ArrayList<>(map.keySet());
And toRemove is where I store the items to be removed from the actual object they are on when the ok button on the original AlertDialog is pressed.
This is how I populate my ListView in the first place:
final ListView list = (ListView) view.findViewById(R.id.list_questions_edit_rack);
list.setAdapter(
new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1,
keys));
I have tried things like list.invalidateViews(), list.invalidate and other things I found in questions similar to mine here on SO. But none of that made any difference. I suspect my problem to be different from theirs since my items clearly are updated, it just takes a change of focus on the original AlertDialog for the change to be visible.
How can I make the ListView show the changes in it's data source imidiatly insted of after a focus change?
By calling
((ArrayAdapter) list.getAdapter()).notifyDataSetChanged();
you get a fresh adapter which is almost certainly not identical to the anonymous adapter you used to populate your list in the first instance.
See also the documentation for ListView.getAdapter()
Returns the adapter currently in use in this ListView.
The returned adapter might not be the same adapter passed to setAdapter(ListAdapter) but might be a WrapperListAdapter.
From the point of view of this fresh adapter, the data set hasn't changed because the changes happened way before it was instantiated.
To solve your problem, make your list and your list adapter members of your activity class (or the scope where you want to keep them alive):
private ArrayList<String> keys;
private ArrayAdapter myAdapter;
private ListView list;
Then in your "onCreate()"
keys = ...; // initialization of ArrayList with the needed data
myAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_activated_1,
keys);
list = (ListView) view.findViewById(R.id.list_questions_edit_rack);
list.setAdapter(myAdapter);
This way, in your "OnClickListener" you can notify "myAdapter":
keys.addAll(map.keySet());
myAdapter.notifyDataSetChanged();
Hope this helps :)
You can tweak it, by granting focus to another view, and then requesting it back:
view.requestFocus();
You can also use:
view.requestFocusFromTouch();
I have got a custom list view adapter and an image button in the adapter class. When i click on the image button, the listener should reload the list view. I need to reload the list view within getview() of adapter class. So I need to know other options than using notifyDataSetChanged() in my listActivity class.
Thanks
You want to refresh a cell inside the listview or do you want to refresh the whole listview, if a single row is loaded inside getView() ?
Check this out:
Android ListView Refresh Single Row
Create a static handler inside the activity which calls a method which reloads the listview and send a message to this handler from the adapter whenever required.
handler = new Handler() {
public void handleMessage(Message paramAnonymousMessage) {
switch (paramAnonymousMessage.what) {
case 1:
populateList();
break;
}
}
};
public void populateBill() {
MyBasketAdapter adapter = new MyBasketAdapter(this, basketList);
listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(adapter);
}
Inside the adapter class. for example,
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Message msg = Message.obtain();
msg.what = 1;
MyActivity.handler.sendMessage(msg);
}
});
That is very Simple just write a method in your adapter class and call it get view when you deleting or adding anything in your list which you are binding to your adapter.and use notifyDataSetChanged after change in list
public void updateResults(ArrayList<CustomList> results) {
// assign the new result list to your existing list it will work
notifyDataSetChanged();
}
In one of my activity I have EditText, Submit Button and a ListView. The data of ListView are retrived from database. To retrive data from database and adapt to ListView I used the following code.
private void loadList() {
mylist = new ArrayList<HashMap<String, Object>>();
mylist.clear();
List<Data> catDesc = dbhelper.getCatMasterDesc(id);
ArrayAdapter<Data> adapter = new SimpleAdapter(getApplicationContext(), R.layout.list, catDesc);
lv1 = (ListView) findViewById(R.id.masListView1);
lv1.setAdapter(adapter);
}
And i call this method every time whenever I update the database to show updated listview.
String str = category.getText().toString();
yes.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
dbhelper.UpdateMasterDesc(str);
loadList(); // see here.
}
});
This is the way I am updating my ListView. I think this is not a good way. If yes means please suggest me how can I update my ListView Whenever I update the database.
Thank You.
notifyDataSetchanged() is the answer as proposed by Raghunandan.
But before calling it, you need to update your object data which has been included in your list of catDesc.
Judging from your code I believe what
dbhelper.UpdateMasterDesc(str);
does is adding a new category? If yes, do a
catDesc.add(new Data(whatever you need to declare it with str))
before calling notifyDataSetChanged().