i have a listview that contains relative views on each list item that are populated by a database and contains two buttons.
when one of the buttons in the list view item is pressed i need to get the id of that row in the list view. in other words i am trying to find the same thing as the last argument in the onItemClick methos for the onItemClickListener(), which would return a click for the entire item. however i am just listening for the button in the listview item so i am unable to use onItemClickListener().
i have this method being called when i click the button
public void plusClick(View v)
{
//get the row the clicked button is in
RelativeLayout vwParentRow = (RelativeLayout)v.getParent();
//i need to get the id of this RelativeLayout item in the list view
TextView child = (TextView)vwParentRow.getChildAt(2);
Button btnChild = (Button)vwParentRow.getChildAt(1);
int c = Color.CYAN;
vwParentRow.setBackgroundColor(c);
vwParentRow.refreshDrawableState();
}
it need to find the id of the relative layout which i can pass ass arg for
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
to create a new cursor contiain the data in this listview item
try this code:
private OnItemClickListener itemClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int position,
long id) {
// write your logic here
// position starts from 0
// id starts from 1
}
};
when you set onclicklistener for your button you can set tag for it(tag can be id of row), and then when you click on button get it's tag. (of course if you use custom adapter)
You need some kind of adapter, in getView method you have to declare your event
There is an example:
holder.hMention.setOnClickListener(new VerTweet(mention));
and...
public class VerTweet implements View.OnClickListener
{
Mention mention;
public VerTweet ( Mention mention) {
this.mention = mention;
}
public void onClick( View view ){
Bundle bundle = new Bundle();
//Le ponemos la variable parametro con el contenido test
bundle.putInt("idTrack", mention.getIdTrack());
bundle.putString("Gifo", mention.getGifo());
bundle.putString("From", mention.getFromUser());
bundle.putString("Date", mention.getDateMentions());
bundle.putString("Text", mention.getText());
bundle.putLong("Status", mention.getLastId());
Intent i = new Intent(getContext(), Tweet.class);
i.putExtras(bundle);
getContext().startActivity(i);
}
}
https://github.com/m-alcu/SkoltiAlert/blob/master/src/com/alcubier/skoltialert/mentions/GDMentionsList.java
Related
I have a ListView that displays an ArrayList that is dynamically created using an adapter. However, certain elements of each list item view are calculated based on previous item values. I am using Intents to open another activity where the user can edit a selected list item, and the updates are passed back to the main activity. In the main activity I've placed the getIntent, and the associated setters, after the ArrayList is generated and before the adapter. When the main activity is first created the adapter correctly calculates all list view items. But when the user accepts updates in the edit activity and returns to the main activity, only the selected list item is updated. Having the entire list cycle through and update would be fine (it will never be a very long list), but I'm a little surprised that only the selected list item is getting updated. I expected that either the adapter would run as it does when the activity is first created and all items would get updated, or that it wouldn't run at all and none would get updated.
public class MainActivity extends AppCompatActivity {
private final Context thisContext = MainActivity.this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView planListView = findViewById(R.id.plan_listview);
final ArrayList<ItemProfile> planSteps = BuildPlan();
if(getIntent().getExtras() != null)
{
int stepNumber = getIntent().getIntExtra("stepNumber", 0);
ItemProfile thisStep = (ItemProfile) getIntent().getSerializableExtra("itemProfile");
planSteps.get(stepNumber-1).setDepth(thisStep.getDepth());
planSteps.get(stepNumber-1).setTime(thisStep.getTime());
planSteps.get(stepNumber-1).setInterval(thisStep.getInterval());
}
ItemsListAdapter planAdapter = new ItemsListAdapter(this, planSteps);
planListView.setAdapter(planAdapter);
planListView.setOnItemClickListener(
new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l)
{
int index = pos-1;
Intent i = new Intent(thisContext, EditItemActivity.class);
i.putExtra("stepNumber", pos);
i.putExtra("stepProfile", planSteps.get(index));
if (index > 0)
{
i.putExtra("groupStart", planSteps.get(index-1).getGroupEnd());
}
startActivity(i);
}
}
);
}
}
Update... I've added the mainActivity code. It creates an ArrayList plan (I'm using a BuildPlan method to populate a dummy plan while I'm developing) then checks for an intent that is returning an updated plan step. If an intent exists the specified step is updated in the plan. The list adapter is then created and set. Finally the clickListener is created and set.
I've done something relatively similar but I used dynamic spinners and listviews from a database.
Here is the code. Basically you invalidate the list view, reset the data and call notifyDataSetChanged() on the adapter.
public ListView lv;
Spinner suburbSpinner;
ArrayAdapter<String> suburbAdapter;
ArrayList<String> suburbs = new ArrayList<>();
ArrayList<Resource> resources = new ArrayList<>();
ArrayAdapter<Resource> arrayAdapter;
public void updateList(String type, String suburb, String businessType, int suburbPos) {
DatabaseHelper db = new DatabaseHelper(this, "fairCanberraDB", null, 1);
lv = findViewById(R.id.list);
// Reset suburb spinner, get new list view resources.
lv.invalidateViews();
resources = db.resourceQuery(type, suburb, businessType);
System.out.println("resource: " + resources);
ArrayList<Resource> suburbQuery = db.resourceQuery(type, "All", businessType);
Spinner suburbSpinner = findViewById(R.id.suburbSpinner);
suburbs.clear();
suburbs.add("All");
for (int x = 0; x < suburbQuery.size(); x++) {
if (suburbs.contains(suburbQuery.get(x).getSuburb())) {
continue;
} else {
suburbs.add(suburbQuery.get(x).getSuburb());
}
}
db.close();
suburbAdapter.notifyDataSetChanged();
arrayAdapter.notifyDataSetChanged();
ArrayAdapter<Resource> arrayAdapter = new ArrayAdapter<Resource>(
this,
android.R.layout.simple_list_item_1,
resources);
lv.setAdapter(arrayAdapter);
if(suburbPos < suburbSpinner.getCount())
{ suburbSpinner.setSelection(suburbPos);}
setSpinnerListener(suburbSpinner);
}
// Register listener for a spinner
public void setSpinnerListener(Spinner spinner)
{
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Spinner typeSpinner = (Spinner) findViewById(R.id.typeSpinner);
Spinner businessTypeSpinner = (Spinner) findViewById(R.id.businessTypeSpinner);
Spinner suburbSpinner = (Spinner) findViewById(R.id.suburbSpinner);
String businessType = businessTypeSpinner.getSelectedItem().toString();
if(businessType.contains("Private"))
{
businessType = "private user";
}
updateList(typeSpinner.getSelectedItem().toString(), suburbSpinner.getSelectedItem().toString(),
businessType, suburbSpinner.getSelectedItemPosition());
}
I have implemented a list View with CheckedTextView . When I am selecting a particular row and clicking on checkbox then checkbox becomes invisible. Also sometimes any other row get selected.I want to select multiple items.
please help...
List_row Layout is..
<CheckedTextView
android:id="#+id/service_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="20sp"
android:layout_marginBottom="10dp"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:textColor="#000000"
android:checked= "false"
>
CustomListView is:
import java.util.ArrayList;
public class CustomListView extends ArrayAdapter {
//to reference the Activity
private final Activity context;
String value;
//to store the list items
private final String[] nameArray;
CheckedTextView nameTextField;
public CustomListView(Activity context, ArrayList nameArra) {
super(context, R.layout.row_list_view, nameArrayParam);
this.context = context;
this.nameArray = nameArrayParam;
}
public View getView(int position, View view, ViewGroup parent)
{
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.row_list_view, null, true);
//this code gets references to objects in the listview_row.xml file
nameTextField = (CheckedTextView)
rowView.findViewById(R.id.service_name);
//this code sets the values of the objects to values from the arrays
nameTextField.setText(nameArray[position]);
// perform on Click Event Listener on CheckedTextView
nameTextField.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v("customList",";clicked row is " +
nameTextField.getText().toString());
if (nameTextField.isChecked()) {
// set check mark drawable and set checked property to false
value = "un-Checked";
nameTextField.setCheckMarkDrawable(R.color.colorAccent);
nameTextField.setChecked(false);
}
else {
// set check mark drawable and set checked property to true
value = "Checked";
nameTextField.setChecked(true);
}
Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
}
});
return rowView;
}
In my MainActivity.java, I have used listView setOnItemClickListener
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
selected_Item = (String) arg0.getItemAtPosition(arg2);
Toast.makeText(AskForService.this, "Clicked item is" + selected_Item, Toast.LENGTH_LONG).show();
}
});
After implementing these code I can see -
ListView with checked TextView
ListView Can Scroll showing all the list items
on clicking a particular row..listview click listener is called and showing the Toast but checkbox becomes white(invisible) and sometimes another row get selected...Please help
Create a model class which contains a flag "isChecked" and set the data according to the model inside adapter
This link might be helpful : https://stackoverflow.com/a/40285759/8770539
Use an arraylist to store checked item's position.
call notifyDataSetChanged() for onclick()
Use this,
if(list.contains(position)) {
nameTextField.setChecked(true);
}
else {
nameTextField.setChecked(false);
}
nameTextField.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(list.contains(position))
{
list.remove(position);
}
else
{
list.add(position);
}
notifyDataSetChanged();
}
});
For a cookbook app I have a screen with a listview of recipe titles a user has saved. When the user clicks on one of the titles (listview item) it will open a new screen and display the full recipe.
I have stored all the recipe information in a sqlite database. So a row consists of a title, category, imagepath and recipe text. What I can't seem to work out is how I can use the recipe title to display the corresponding recipe text in the new activity.
So this is the onCreate of activity with the title ListView:
// Analyze cursor object: Is there data available on the cursor object?
if (cursor!=null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
// Get information from the cursor object
String imagePath;
String titles;
titles = cursor.getString(0);
imagePath = cursor.getString(1);
// Get the titles and image paths from the database
RecipeDataProvider recipeDataProvider = new RecipeDataProvider(convertSrcToBitmap(imagePath), titles);
// Add them to the listview
adapter.add(recipeDataProvider);
}
while (cursor.moveToNext());
}
}
// Set onclicklistener for the recipe titles.
viewTitlesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Get the index of the title in the database
String index = ((TextView) findViewById(R.id.recipeTitle)).getText().toString();
// TODO get corresponding recipe text
Bundle dataBundle = new Bundle();
dataBundle.putString("id", index);
// Go to ShowRecipeActivity
Intent showIntent = new Intent(view.getContext(), ShowRecipeActivity.class);
showIntent.putExtras(dataBundle);
startActivity(showIntent);
}
});
}
This is the activity where I retrieve the data. At the moment it only shows the title of the recipe again:
// Get the recipe title from the previous activity
Bundle extras = getIntent().getExtras();
mRecipeTitle = extras.getString("id");
recipeTitleView.setText(mRecipeTitle);
// TODO: Get the corresponding recipe text from the database
And this is the cursor method in my DatabaseHelper:
public Cursor getRecipeInfo(SQLiteDatabase db){
// Create object of Cursor
Cursor cursor;
// Create some projections: the needed column names.
String[] projections = {RecipeContract.NewRecipeInfo.RECIPE_TITLE,
RecipeContract.NewRecipeInfo.RECIPE_PHOTO, RecipeContract.NewRecipeInfo.RECIPE_TEXT};
cursor = db.query(RecipeContract.NewRecipeInfo.TABLE_NAME, projections, null, null, null, null, null);
return cursor;
}
I have been stuck on this problem for a while now, I hope you can help me!
You should create a another activity to implement this. Once you click on the recipe list your onclick listener should take you to next activity
where you have to pass the recipe id.
#Override
public void onClick(View v) {
Intent intent= new Intent(this, SecondActivity.class);
intent.putExtra("recipeID", "0000002");
}
I have this code inside my BaseAdapter Adapter:
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.facebook_friends_layout, null);
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName); // Friends thumb
friend_image=(ImageView)vi.findViewById(R.id.ivFacebookPicture); // thumb image
song= new HashMap<String, String>();
song = data.get(position);
friendsName.setText(song.get(MyFriends.KEY_FBNAME));
//Log.i("Facebook Pangalan", ""+MyFriends.KEY_FBNAME);
FriendName = (String) friendsName.getText().toString();
FBID = song.get(MyFriends.KEY_FBID);
String fbAvatarUrl = "http://graph.facebook.com/"+ FBID +"/picture";
//Log.i("FBID", FBID);
BitmapManager.INSTANCE.loadBitmap(fbAvatarUrl, friend_image, 100,100);
Button btn=(Button)vi.findViewById(R.id.btnAdd);
if (FBID.equals(""))
{
btn.setVisibility(View.GONE);
}
else
{
btn.setVisibility(View.VISIBLE);
}
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+FriendName);
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
return vi;
}
I am logging my friend's name whenever I click on the button. Now my problem starts when I click the button; I am not getting my desired string. It is getting the string from another row of my listview.
EDIT
Thanks, actually ive just aaded this code
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//Object x =btn.getTag();
//String sa = x.toString();
View parentView = (View) arg0.getParent();
String textviewtext = ((TextView) parentView.findViewById(R.id.hiddentv)).getText().toString();
//FACEBOOK FRIENDS
AddfromFacebookFriends(textviewtext);
}
else if (LOCK_BASEDATA.equals("1"))
{
I am just getting my parents View to get my desired textview and now it works. Thanks anyway
You are trying to get the FriendName using this code:
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
This is not The FriendName of the ListView item you clicked. Its the FriendName of the newly created ListView item. Because in getView(), the ListView item you get is the newly created one.
One way to solve this is:
Use tags like KunalK suggested. I am not sure if it works...i never tried it.
Or the other way is:
onButtonClicked get the Position of the ListView item you clicked, and get the respective Name from the ArrayList you are using.
Here the Position is not the position parameter in the getView(). That gives the position of the newly created ListView item again.
Use this to get the actual position of the clicked item:
int clickedItemPosition = yourListView.getPositionForView((View) yourButton.getParent());
you should go with this by setting the "FriendName" in your button's setTag property. and whenever you handle your button click event fetch your FriendName String by using getTag property of button. for e.g. something like this:
....
btn.setTag(FriendName);
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+btn.getTag().toString());
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
....
Getting the name from the list can be accompished by using an onListItemClick method as follows (not in your adapter, but in the class with your list):
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
TextView friendsName = (TextView)v.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
}
Since this code is the onListItemClick method, the View v parameter is the view of the row you clicked. Once you have that, you search that particular row view for the TextView you want and then pull the string from that.
You had the right idea, you just put it in the wrong place.
I have an activity that extends ExpandableListActivity. I use SimpleCursorTreeAdapter to fill ExpandableListView.
My layout contains list view and empty view.
On app start ExpandableListActivity automatically chooses the right view to display.
My steps:
App starts, there is no data. (empty view on the screen)
Insert some data into db.
Call adapter.notifyDataSetChanged(); But empty view is still on the screen and there is no any item in my list view.
Then I restart app:
List view appears. I expand all groups and scroll to the bottom.
I click on the item in the list. New activity appears.
Click back button. All groups are collapsed and we are at the top of the screen. Scroll position and expanded groups are not remembered.
Delete all data from db and call adapter.notifyDataSetChanged();
Child views have disappeared, but top-level groups are still visible.
Questions:
What can I do to replace empty view with list view?
What can I do to do to save state of groups and scroll position of the list view?
Tested on SDKs: 1.5r3, 1.6r1
Code:
public class MainActivity extends ExpandableListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dbHelper = new DBOpenHelper(this);
rubricsDbAdapter = new RubricsDBAdapter(dbHelper);
rubricsDbAdapter.open();
itemsDbAdapter = new ItemsDBAdapter(dbHelper);
itemsDbAdapter.open();
rubricsCursor = rubricsDbAdapter.getAllItemsCursor();
startManagingCursor(rubricsCursor);
// Cache the ID column index
rubricIdColumnIndex = rubricsCursor.getColumnIndexOrThrow(RubricsDBAdapter.KEY_ID);
// Set up our adapter
mAdapter = new MyExpandableListAdapter(rubricsCursor,
this,
android.R.layout.simple_expandable_list_item_1,
android.R.layout.simple_expandable_list_item_1,
new String[] {RubricsDBAdapter.KEY_NAME},
new int[] {android.R.id.text1},
new String[] {ItemsDBAdapter.KEY_NAME},
new int[] {android.R.id.text1});
setListAdapter(mAdapter);
}
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Intent i = new Intent(this, ItemViewActivity.class);
i.putExtra(ItemsDBAdapter.KEY_ID, id);
startActivity(i);
return super.onChildClick(parent, v, groupPosition, childPosition, id);
}
private void updateMyData() {
int i;
int k;
long rubricId;
for (i = 1; i <= 5; i++) {
rubricId = rubricsDbAdapter.insert("rubric " + i);
for (k = 1; k <= 5; k++) {
itemsDbAdapter.insert("item " + i + "-" + k, rubricId);
}
}
mAdapter.notifyDataSetChanged();
}
private void deleteMyData() {
rubricsDbAdapter.deleteAll();
itemsDbAdapter.deleteAll();
mAdapter.notifyDataSetChanged();
}
public class MyExpandableListAdapter extends SimpleCursorTreeAdapter
{
public MyExpandableListAdapter(Cursor cursor, Context context, int groupLayout,
int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom,
int[] childrenTo) {
super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom,
childrenTo);
}
#Override
protected Cursor getChildrenCursor(Cursor notebookCursor) {
// Given the group, we return a cursor for all the children within that group
long id = notebookCursor.getLong(rubricIdColumnIndex);
Cursor itemsCursor = itemsDbAdapter.getRubricItemsCursor(id);
startManagingCursor(itemsCursor);
return itemsCursor;
}
}
}
So, the answer is:
Call cursor.requery() before calling adapter's notifyDataSetChanged() method.
Save groups state in activity's onPause() method and restore in onResume() method.
Re: Question # 2...
Why can't you simply call View.invalidateViews() and View.requestLayout() in that order?
If you already have your adapter set to the view, then you shouldn't need to requery, do you? By invalidating the view, and requesting the layout, you won't lose any of the states of your view.
For example, in your "onResume" method, invalidate your list view by calling something like "lv.invalidateViews()". Next, call "lv.requestLayout()".
Your "onCreate" method should still be responsible for setting up the adapters and linking an adapter to the view. To link the adapter, consider using "lv.setListAdapter()" instead of the former so that you aren't messing with the other views on the screen.