Dynamically refresh ListView with CursorAdapter - Java for Android App Development

Hi everyone,
First of all, I'd like to apologize if I'm posting this in a wrong place... This is my first post, I'm still getting familiar with this forum.
I would also like to apologize for the lengthy post.
The title, to a certain extent, reflects what my problem is, but to clarify:
I'm learning Android, so I'm making a simple SMS app for practice.
In it, I have a database which has tables for sent messages, received messages and contacts. I have 3 separate activities (which do NOT extend ListActivity) which show lists for sent messages, received messages and contacts, respectively. The lists are populated through CursorAdapter.
Let's consider the activity for contacts...
In it I have list (ListView) which displays contacts (each list element displays name and phone number). Below the list I have a "Add Contact" button. When I click the button a dialog pops up and shows the form for adding new contact. The buttons in the dialog preform all the database operations.
Similarly, when I click some item in the ListView, another dialog pops up. That dialog has buttons for "Send SMS", "Edit" and "Delete" contact. Again, the buttons do all the work with the database.
The trouble:
My trouble is... When I add a new contact, or delete one (after both operations their dialogs dismiss), the ListView is not refreshed.
In order to see the refreshed list I need to close the activity and start it again.
I googled and googled this for 3 days now, and all the answers I found say that I need to call
Code:
adapter.notifyDataSetChanged
and
Code:
adapter.changeCursor
but that doesn't do the trick.
I'll now post the relevant code with the two methods mentioned above. I placed them where i thought they should be, but this doesn't work.
So, I humbly beg someone to guide me through this ordeal.
Many thanks in advanced!
Here comes the code:
The Adapter:
Code:
public class AdapterContactListView extends CursorAdapter {
private MyDatabaseHelper mdbh;
private LayoutInflater myLayoutInflater;
public AdapterContactListView(Context context, Cursor c, int flags) {
super(context, c, flags);
mdbh = MyDatabaseHelper.getMyDatabaseHelper(context);
myLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// TODO Auto-generated method stub
TextView fullNameTV = (TextView)view.findViewById(R.id.contactElementNameTV);
TextView phoneNumberTV = (TextView)view.findViewById(R.id.contactElementNumberTV);
String fullName = cursor.getString(cursor.getColumnIndex(mdbh.getContactFirstName()));
fullName = fullName.concat(" ");
fullName = fullName.concat(cursor.getString(cursor.getColumnIndex(mdbh.getContactLastName())));
String phoneNumber = cursor.getString(cursor.getColumnIndex(mdbh.getContactPhoneNumber()));
fullNameTV.setText(fullName);
phoneNumberTV.setText(phoneNumber);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// TODO Auto-generated method stub
return myLayoutInflater.inflate(R.layout.contact_element, parent, false);
}
}
And the Activity:
Code:
public class ContactsActivity extends Activity {
private MyUtilities myUtilities;
private MyDatabaseHelper mdbh;
private AdapterContactListView contactsAdapter;
private ListView contactsListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts);
mdbh = MyDatabaseHelper.getMyDatabaseHelper(this);
myUtilities = new MyUtilities(this);
contactsAdapter = new AdapterContactListView(this,mdbh.getContactsCursor(),CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
contactsListView = (ListView)findViewById(R.id.contactActivityLV);
contactsListView.setAdapter(contactsAdapter);
contactsListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
TextView phoneNumberTV = (TextView)view.findViewById(R.id.contactElementNumberTV);
String phoneNumber = phoneNumberTV.getText().toString();
Contact contact = mdbh.getContactFromPhoneNumber(phoneNumber);
Dialog d = myUtilities.createSelectedContactOptionsDialog(contact);
d.show();
contactsAdapter.changeCursor(mdbh.getContactsCursor());
contactsAdapter.notifyDataSetChanged();
}
});
}
public void addContact(View view) {
Dialog d = myUtilities.createAddContactDialog();
d.show();
contactsAdapter.changeCursor(mdbh.getContactsCursor());
contactsAdapter.notifyDataSetChanged();
}
}

djolec987 said:
Hi everyone,
Click to expand...
Click to collapse
Well notifyDatasetChanged only informs the adapter that the backing interface has new data... but your backing it with a cursor... so in your case it would just cause getView/bindView to be called for all current visible items, thus fire a query at the cursor. I think the cursor will cache the data so it's really a reload on the cursor data and then an adapter notify call you want... If you use loader (depending on target api version) then it should do most of this for you. As it stands if you want to do it manually make sure the cursor is a new cursor of the database that has changed.
(typed in a rush)

Related

Enabling selection in textview

I am using this android:textIsSelectable and still gets the error:
Code:
TextView does not support text selection. Action mode cancelled.
Can any one please tell me what I might be doing wrong?
obscurant1st said:
I am using this android:textIsSelectable and still gets the error:
Code:
TextView does not support text selection. Action mode cancelled.
Can any one please tell me what I might be doing wrong?
Click to expand...
Click to collapse
Please post the code and also the AP version you are testing the app cant say anything without that
I believe testIsSelectable for TextViews was introduced in Honeycomb, if you want to be able to mimic that feature with lower versions of Android, here's a little workaround :
Use an EditText instead of your TextView and set android:textIsSelectable to false
In your activity's java code, override onLongClickListener and set the EditText to selectable in this method, something like this :
Code:
public class yourClass extends Activity implements onLongClickListener {
EditText yourFakeTextView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.whatever);
yourFakeTextView = (EditText) findViewById(R.id.editText1);
yourFakeTextView.setOnLongClickListener(this);
}
@Override
public boolean onLongClick(View v) {
switch (v.getId()) {
case R.id.editText1:
yourFakeTextView.setTextIsSelectable(true);
break;
default:
return;
}
return false;
}
}
This will make the EditText look like a regular TextView, and when the user long-clicks it, it will allow him to select the text (just like if it was a normal, selectable TextView).
Hope this helps.
I want to enable this feature on ICS and upper version of android. I am testing this on an ics device. There is something which is messed up. I will post the code as soon as I reach home!

[Q] No idea how to load onChildClick in my ExpandableListView.

I have an expandable list view with 2 parents and 3 children. I want to open a dialog based on each click. I can't find any examples showing you how to call something based on positions. At least not with the ExpandableListView tutorial I followed.
Code:
public class MainActivity extends Activity implements OnClickListener {
private LinkedHashMap<String, HeaderInfo> myDepartments = new LinkedHashMap<String, HeaderInfo>();
private ArrayList<HeaderInfo> deptList = new ArrayList<HeaderInfo>();
private MyListAdapter listAdapter;
private ExpandableListView myList;
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Just add some data to start with
loadData();
// get reference to the ExpandableListView
myList = (ExpandableListView) findViewById(R.id.myList);
// create the adapter by passing your ArrayList data
listAdapter = new MyListAdapter(MainActivity.this, deptList);
// attach the adapter to the list
myList.setAdapter(listAdapter);
// listener for child row click
myList.setOnChildClickListener(myListItemClicked);
// listener for group heading click
myList.setOnGroupClickListener(myListGroupClicked);
}
// load some initial data into out list
private void loadData() {
addProduct("Parent One", "Child One");
addProduct("Parent One", "Child Two");
addProduct("Parent One", "Child Three");
addProduct("Parent Two", "Child One");
addProduct("Parent Two", "Child Two");
addProduct("Parent Two", "Child Three");
}
// our child listener
private OnChildClickListener myListItemClicked = new OnChildClickListener() {
[user=439709]@override[/user]
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// Create a switch that switches on the specific child position.
// get the group header
HeaderInfo headerInfo = deptList.get(groupPosition);
// get the child info
DetailInfo detailInfo = headerInfo.getProductList().get(
childPosition);
// display it or do something with it
// custom dialog
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.cdialog);
// dialog.setTitle(R.id.titlebar);
dialog.setTitle(R.string.titlebar);
dialog.show();
return false;
}
};
// our group listener
private OnGroupClickListener myListGroupClicked = new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
// get the group header HeaderInfo headerInfo =
deptList.get(groupPosition);
// display it or do something with it
return false;
}
};
I can get a custom dialog open if I click a child, but it's not set to any specific parent and child.
Any ideas?
EDIT ADD: Got it. Tried a switch/case like this and it worked. Finally! After two days of trying to understand it.:fingers-crossed:
Code:
switch(groupPosition) {
case 1:
switch (childPosition) {
case 0:
Intent protheanIntent = new Intent(Codex.this, CodexProthean.class);
Codex.this.startActivity(protheanIntent);
break;
case 1:
Intent rachniIntent = new Intent(Codex.this, CodexRachni.class);
Codex.this.startActivity(rachniIntent);
break;
}
case 2:
switch (childPosition) {
case 2:
Intent asariIntent = new Intent(Codex.this, CodexAsari.class);
Codex.this.startActivity(asariIntent);
break;
}
}

A question about list

Hi.
I am building an app that has a list. All of the clicks on list items result in one activity, like XActivity. XActivity contains a text view. I want that when I click on ListItem1 the text view shows a string forexample string1, then onClickListItem2 it shows string2, onListItemClicX it shows stringX. If it's confusing let me know.
How can I handle it ?
Thanks in advance.
torpedo mohammadi said:
Hi.
I am building an app that has a list. All of the clicks on list items result in one activity, like XActivity. XActivity contains a text view. I want that when I click on ListItem1 the text view shows a string forexample string1, then onClickListItem2 it shows string2, onListItemClicX it shows stringX. If it's confusing let me know.
How can I handle it ?
Thanks in advance.
Click to expand...
Click to collapse
I'm assuming you're using an ArrayAdapter - it would be helpful if you posted some code.
You have to setup an OnItemClickListener for your ListView. In the OnItemClick method, you will have to get the data from the adapter using the position that was clicked. Then create an intent to ActivityX and pass the clicked data.
Code:
[B]ArrayAdapter adapter = new ArrayAdapter();[/B]
listView.setClickable(true);
//Setup the on item click listener for the listview
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Create an intent pointing to XActivity
Intent intent = new Intent(this, XActivity.class);
//Add the clicked string as an extra
intent.putExtra("KEY_CLICKEDSTRING", adapter.getItem(position - 1));
//Start the activity
this.startActivity(intent);
}
});
In ActivityX, simply retrieve the data and set it in the textview:
Code:
@Override
public void onCreate(Bundle savedInstanceState) {
... Activity setup code
TextView textView = findViewById(R.id.yourtextview);
//Get the intent data
String strClicked = getIntent().getStringExtra("KEY_CLICKEDSTRING");
textView.setText(strClicked);
}
Thank you.
But I don't know what value does the "int position" give me ? Forexample does it give the value of "1" or .... ?
I want to know that in order to know which item was clicked and now what to do .
Can anybody help me ?
Thanks in advance.
Like previously mentioned. Post your code and we can help you out better.
not complex, First I make a new ArrayAdapter<string> add adapt it to my listView. Up to know no problem. But in the continue :
// usual codes to answer a click onItemClick(AdapterView<?> av, View v, int position, long id) {
//create a intent as Alkonic said
//My problem }
...
@My problem I want to use a set of codes and understand which item was clicked. I have 41 items and my idea is this :
// getting the text of the clicked item String title = ((TextView)v).getText().toString();
If (title=getString(R.string.theTextIHadAddedToArrayAdapterForItem1)) {
// so item 1 was clicked
//Change the text of thesecond TextView in the second activity ( wich I wrote intent for)
// rewrite the if order 41 times for 41 items
...
But this doesn't work. Can anybody help me ?
@Alconic :
I don't understand the method you wrote for retrieving intent data ( I mean
//Get the intent data String strClicked = getIntent().getStringExtra("KEY_CLICKEDSTRING");
) because the "Key_CLICKEDSTRING" is always constant and one thing. How can I cange it for 41 items ?
Thank you guys anyway.
not complex, First I make a new ArrayAdapter<string> add adapt it to my listView. Up to know no problem. But in the continue :
// usual codes to answer a click onItemClick(AdapterView<?> av, View v, int position, long id) {
//create a intent as Alkonic said
//My problem }
...
@My problem I want to use a set of codes and understand which item was clicked. I have 41 items and my idea is this :
// getting the text of the clicked item String title = ((TextView)v).getText().toString();
If (title=getString(R.string.theTextIHadAddedToArrayAdapterForItem1)) {
// so item 1 was clicked
//Change the text of thesecond TextView in the second activity ( wich I wrote intent for)
// rewrite the if order 41 times for 41 items
...
But this doesn't work. Can anybody help me ?
@Alconic :
I don't understand the method you wrote for retrieving intent data ( I mean
//Get the intent data String strClicked = getIntent().getStringExtra("KEY_CLICKEDSTRING");
) because the "Key_CLICKEDSTRING" is always constant and one thing. How can I cange it for 41 items ?
Thank you guys anyway.
You should post your onItemClick routine. But for going at it blind on our side this is what I would do:
Code:
public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
//Get text from a textview that is on your listview
TextView textView2 = (TextView) v.findViewById(R.id.myTextView);
String txtMytext = textView2.getText().toString();
//Create an intent pointing to XActivity
Intent intent = new Intent(this, XActivity.class);
//Add the clicked string as an extra
intent.putExtra("KEY_CLICKEDSTRING", txtMytext);
//Start the activity
this.startActivity(intent);
}
Without your code, I don't understand what you are comparing with the if statement you posted. Use this along with @Alkonic 's code should get you in the right direction. If it doesn't, we need more code to help better.
torpedo mohammadi said:
not complex, First I make a new ArrayAdapter<string> add adapt it to my listView. Up to know no problem. But in the continue :
// usual codes to answer a click onItemClick(AdapterView<?> av, View v, int position, long id) {
//create a intent as Alkonic said
//My problem }
...
@My problem I want to use a set of codes and understand which item was clicked. I have 41 items and my idea is this :
// getting the text of the clicked item String title = ((TextView)v).getText().toString();
If (title=getString(R.string.theTextIHadAddedToArrayAdapterForItem1)) {
// so item 1 was clicked
//Change the text of thesecond TextView in the second activity ( wich I wrote intent for)
// rewrite the if order 41 times for 41 items
...
But this doesn't work. Can anybody help me ?
@Alconic :
I don't understand the method you wrote for retrieving intent data ( I mean
//Get the intent data String strClicked = getIntent().getStringExtra("KEY_CLICKEDSTRING");
) because the "Key_CLICKEDSTRING" is always constant and one thing. How can I cange it for 41 items ?
Thank you guys anyway.
Click to expand...
Click to collapse
Handling Clicks:
The int position refers to the position of the item that was clicked in the arrayadapter.
Instead of this:
Code:
String title = ((TextView)v).getText().toString();
you can use
Code:
String title = adapter.getItem(position);
That code will take the clicked position and get the clicked string from the adapter.
Intent Data
When you send data with an intent, it has two parts: the Name and Value.
The following code sets the name to a constant "Key_CLICKEDSTRING" and the Value is variable, depending on what was clicked.
Code:
intent.putExtra("KEY_CLICKEDSTRING", adapter.getItem(position));
When you want to access the VALUE, you have to provide the constant name:
Code:
String strClicked = getIntent().getStringExtra("KEY_CLICKEDSTRING");
Hope that helped!

[Q] Code not bringing desired results

good day,
i'm trying to create an app that will create options in a listview on an an activity based on the option a user selects in the previous activity
below is the code i came up with but it doesn't work.
please what am i doing wrong?
thanks in advance
package com.inveniotech.moneyventure;
/**
* Created by BolorunduroWB on 9/3/13.
*/
import android.os.Bundle;
import android.app.Activity;
import android.view.*;
import android.widget.*;
import java.util.*;
import android.content.Intent;
public class menu_options extends Activity {
SimpleAdapter simpleAdpt;
Intent intent = getIntent();
public String message = intent.getStringExtra(football.EXTRA_MESSAGE);
String[] menuList;
@override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menuoptionsview);
initList();
// We get the ListView component from the layout
ListView lv = (ListView) findViewById(R.id.listView);
// This is a simple adapter that accepts as parameter
// Context
// Data list
// The row layout that is used during the row creation
// The keys used to retrieve the data
// The View id used to show the data. The key number and the view id must match
simpleAdpt = new SimpleAdapter(this, optionList, android.R.layout.simple_list_item_1, new String[] {"options"}, new int[] {android.R.id.text1});
lv.setAdapter(simpleAdpt);
// React to user clicks on item
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id) {
// We know the View is a TextView so we can cast it
TextView clickedView = (TextView) view;
Toast.makeText(menu_options.this, "Item with id ["+id+"] - Position ["+position+"] - Planet ["+clickedView.getText()+"]", Toast.LENGTH_SHORT).show();
}
});
}
@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;
}
// The data to show
List<Map<String, String>> optionList = new ArrayList<Map<String,String>>();
private void initList() {
// We populate the planets
if (message.equals("5")){
menuList = new String[]{"News", "Fixtures","Results","Standings"," "};
}
else if (message.equals("6")){
menuList = new String[]{"News", "Tables"," "," "," "};
}
else if (message.equals("7")){
menuList = new String[]{"Done Deals", "Rumours","Latest News","Live","Transfer Centre"};
}
else {
menuList = new String[] {"News","Teams","Fixtures","Results","Table"};
}
optionList.add(createOptions("options", menuList[0]));
optionList.add(createOptions("options", menuList[1]));
optionList.add(createOptions("options", menuList[2]));
optionList.add(createOptions("options", menuList[3]));
optionList.add(createOptions("options", menuList[4]));
}
private HashMap<String, String> createOptions(String key, String name) {
HashMap<String, String> options = new HashMap<String, String>();
options.put(key, name);
return options;
}
}
Read This guide first, then it's easier to help you.
What I'm seeing is that you should set your message=getIntent ().... ; in the onCreate since the Intent data is probably not available before.
SimplicityApks said:
Read This guide first, then it's easier to help you.
What I'm seeing is that you should set your message=getIntent ().... ; in the onCreate since the Intent data is probably not available before.
Click to expand...
Click to collapse
Thank you. Wanted to post the link, too. :laugh:

Android Studio Fragments using Java

I'm working in a project that have 3 Fragments (List, Add and Update fragments)
The List Fragment have a RecyclerView and FloatingActionButton to add a new record.
the Add Fragments have the fields (EditText) to Add New Record
and the Update Fragment have the fields (EditText) to change Data and update.
When a new record is added, the data for this record can be viewed in the recycler. And clicking on any item in the recycler gives you the opportunity to delete or show the data of this item in the UpdateFragment.
my problem is that simple project is near to be finished but I have a big problem:
I'm not know how to send the data of clicked item on the RecyclerView to the UpdateData Fragment to show this data on the EditText in UpdateFragment and updat if I desire.
I'm created a Click.Listener on the RecyclerView Adapter when I click a row_layout in RecyclerView:
@override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Model model = arrayList.get(position);
final String id = model.getId();
final String titulo = model.getTitulo();
final String prioridad = model.getPrioridad();
final String descripcion = model.getDescripcion();
final String addTimeStamp = model.getAddTimeStamp();
final String updateTimeStamp = model.getUpdateTimeStamp();
// set views
holder.titulo.setText(titulo);
holder.descripcion.setText(descripcion);
// colorea el ImageView
switch(prioridad){
case "ALTA": holder.itemView.findViewById(R.id.priority_indicator).setBackgroundColor(Color.parseColor("#FF4646")); break; // rojo
case "MEDIA": holder.itemView.findViewById(R.id.priority_indicator).setBackgroundColor(Color.parseColor("#FFC114")); break; // amarillo
case "BAJA": holder.itemView.findViewById(R.id.priority_indicator).setBackgroundColor(Color.parseColor("#00C980")); break; // verde
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
//Toast.makeText(context, "CLICK EN UN ITEM", Toast.LENGTH_SHORT).show()
editDialog(
""+position,
""+id,
""+titulo,
""+prioridad,
""+descripcion,
""+addTimeStamp,
""+updateTimeStamp
);
}
});
//This take me to Update Fragment but I'm not have a way to send the holder data (id, titulo, prioridad, description) to UpdateFragment
holder.row_layout.setOnClickListener(new View.OnClickListener() {
@override
public void onClick(View v) {
Navigation.findNavController(v).navigate(R.id.action_listFragment_to_editRecordFragment);
}
});
}
Can anyone please know how to solve this problem?
Thank in advanced to all for read.

Categories

Resources