I have an activity lets call it Activity 1 and there we will have a ListView composed by Player objetcs. When you click on a ListView_item (on a Player) a new activity starts, lets call it Activity 2. What I want is:
Activity 1 sends to Activity 2 player's name and player's race. In Activity 2 the user could edit that (player's name and player's race) and when the user click on Confirm Ativity 2 sends to Activity 1 the player's name and player's race even I the user has not edited it (in that case it would send the previus that Activity 1 has sended to Activity 2).
The problem is that when I'm suposse to use startActivityForResult I'm into ListViewAdapter class and using context.start... startActivityForResult doesn't appears.
public class AdaptadorJugadores extends BaseAdapter implements ListAdapter {
private ArrayList<Jugador> list = new ArrayList<Jugador>();
private Context context;
public AdaptadorJugadores(ArrayList<Jugador> list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return 0;
//just return 0 if your list items do not have an Id variable.
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.item_lista_jugadores, null);
}
//Handle TextView and display string from your list
TextView TextoNombreJugador = (TextView)view.findViewById(R.id.etNombreJugador);
TextoNombreJugador.setText(list.get(position).getNombre());
if (list.get(position).getGenero() == "Hombre"){
TextoNombreJugador.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_face_black_24dp, 0, 0, 0);
}else{
TextoNombreJugador.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_face_black_girl24dp, 0, 0, 0);
}
//Handle buttons and add onClickListeners
Button deleteBtn = (Button)view.findViewById(R.id.btEliminarJugador);
deleteBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
list.remove(position); //or some other task
notifyDataSetChanged();
}
});
/*addBtn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
//do something
notifyDataSetChanged();
}
});*/
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Send single item click data to SingleItemView Class
Intent intent = new Intent(context, VistaJugador.class);
intent.putExtra("Nombre",(list.get(position).getNombre()));
intent.putExtra("Genero",(list.get(position)).getGenero());
// Start SingleItemView Class
}
});
return view;
}
}
You could use the ListView's setOnItemClickListener(AdapterView.OnItemClickListener listener) method and in there you could start the activity using startActivityForResult.
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// get the data to pass to the activity based on the position clicked
Intent intent = new Intent(...);
intent.setExtra(...);
startActivityForResult(...);
}
});
Alternatively, you could pass the Activity to your adapter and use that instead of a context, but the first solution is preferable.
I suggest you to pass the context from the Activity to the Adapter, then store it in a local variable. After that, you can just use it to startActivityForResult, but note that you have to implement the onActivityResultMethod. My suggestion is that you use an interface, then pass the ID of the selected item and call the startActivityForResult() in the Activity.
Related
I need to PASS THE DATA (videoId) from inside this custom ArrayAdapter back to the fragment that holds it when the user clicks on the favorite button.
I also need to PASS THE DATA of the song's position back to the fragment if the user clicks the layout of the song. (Both onclicks defined below.)
Previously, the position of the song was passed to the containing fragment SelectSongFragment via this method:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//pass data to main activity
//TODO THIS NO LONGER RUNS
String songUrl = urlCleaner.parseIntoUrl(mSongs.getSong(i).getVideoId(), false);
passData(songUrl);
}
});
After I added the onclick Listeners to the arrayAdapter, mListView.setOnItemClickListener stopped working, and now I have no way to pass any data back! Check my custom ArrayAdapter below, and look for "HELP NEEDED HERE" Thanks very much!
public class SelectSongArrayAdapter extends ArrayAdapter<Song> implements AppInfo {
private ArrayList<Song> songs;
private ArrayList<String> mFavoriteSongs;
private boolean isFavorite = false;
private Song song;
/**
* Override the constructor for ArrayAdapter
* The only variable we care about now ArrayList<PlatformVersion> objects
* it is the list of the objects we want to display
*
* #param context
* #param resource
* #param objects
*/
public SelectSongArrayAdapter(Context context, int resource, ArrayList<Song> objects, ArrayList<String> favoriteSongVideoIds) {
super(context, resource, objects);
this.songs = objects;
this.mFavoriteSongs = favoriteSongVideoIds;
}
/**
* Primary functionality to create a list in the view of songs and song detail lines.
*
* #param position
* #param convertView
* #param parent
* #return
*/
public View getView(int position, View convertView, ViewGroup parent) {
// assign the view we are converting to a local variable
View view = convertView;
/*
Check to see if view null. If so, we have to inflate the view
"inflate" basically mean to render or show the view
*/
if (view == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.detail_line_song, null);
}
song = songs.get(position);
// obtain a reference to the widgets in the defined layout "wire up the widgets from detail_line"
TextView songTitle = (TextView) view.findViewById(R.id.songTitle);
TextView songDescription = (TextView) view.findViewById(R.id.songDescription);
View viewSongLayout = view.findViewById(R.id.songLayout); //For when user clicks left side of view
final ImageButton favoriteStarButton = (ImageButton) view.findViewById(R.id.favorite);
//Find out if song is favorite or not:
isFavorite = false;
for (String songId : mFavoriteSongs) {
if (song.getVideoId().equals(songId)) {
//Is not a favorite song. Do nothing
} else {
//Is a favorite song
isFavorite = true;
break;
}
}
//TODO Testing with multiple favorite songs.
songTitle.setText(song.getDisplayName());
songDescription.setText(song.getDescription());
favoriteStarButton.setPressed(isFavorite); //Changes star color
//Add Listeners
favoriteStarButton.setOnClickListener(new View.OnClickListener() { //Star button click
#Override
public void onClick(View v) {
isFavorite = !isFavorite;
if (isFavorite) {
//Add to favoriteVideoIds
/************************************************
HELP NEEDED HERE:
NEED TO PASS DATA (song.getVideoId()) BACK TO THE FRAGMENT SOMEHOW TO
REMOVE SONG FROM FAVORITES LIST OF SONGS STORED IN THE ACTIVITY
NOT HERE IN THE ARRAYADAPTER)
********************************************************************/
} else {
//remove from favoriteVideoIds
/************************************************
HELP NEEDED HERE:
NEED TO PASS DATA (song.getVideoId()) BACK TO THE FRAGMENT SOMEHOW TO
ADD SONG TO FAVORITES LIST OF SONGS STORED IN THE ACTIVITY
NOT HERE IN THE ARRAYADAPTER)
********************************************************************/
}
v.setPressed(isFavorite); //Changes star color
//redraw view
v.invalidate();
}
});
//Listener for when song is clicked (left side of listview)
viewSongLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/******************************************************************
SAME PROBLEM HERE. NEED TO PASS DATA (POSITION) OF THE SONG THAT WAS CLICKED BACK TO THE FRAGMENT.
********************************/
return view;
}
}
You can create an interface for your click events :
interface ClickEvents {
void onFavoriteStarButtonClick(boolean isFavorite, int position);
void onViewSongLayoutClick(int position);
}
Specify an instance of ClickEvents as an argument inside your ArrayAdapter constructor :
private ClickEvents clickEvents;
public SelectSongArrayAdapter(Context context, int resource, ArrayList<Song> objects, ArrayList<String> favoriteSongVideoIds, ClickEvents clickEvents) {
super(context, resource, objects);
this.songs = objects;
this.mFavoriteSongs = favoriteSongVideoIds;
this.clickEvents = clickEvents;
}
Call the appropriate methods of ClickEvents inside your onClick methods :
favoriteStarButton.setOnClickListener(new View.OnClickListener() { //Star button click
#Override
public void onClick(View v) {
isFavorite = !isFavorite;
clickEvents.onFavoriteStarButtonClick(isFavorite, position);
}
});
viewSongLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clickEvents.onViewSongLayoutClick(position);
}
}
Finally pass an implementation of ClickEvents to your adapter as a parameter :
final ClickEvents clickEvents = new ClickEvents() {
#Override
public void onFavoriteStarButtonClick(boolean isFavorite, int position) {
// FavoriteStarButton clicked
}
#Override
public void onViewSongLayoutClick(int position) {
// ViewSongLayout clicked
}
};
final SelectSongArrayAdapter selectSongArrayAdapter = new SelectSongArrayAdapter(getContext(), resource, objects, favoriteSongVideoIds, clickEvents);
With the following code I'm correctly receiving a dynamic list from mysql db and putting the elements in a listview.
public class MenuActivity extends ListActivity implements FetchDataListener {
private ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
initView();
}
private void initView() {
// show progress dialog
dialog = ProgressDialog.show(this, "", "Loading..");
String url = "http://www.*********.php";
FetchDataTask task = new FetchDataTask(this);
task.execute(url);
}
#Override
public void onFetchComplete(List<Application> data) {
// dismiss the progress dialog
if(dialog != null) dialog.dismiss();
// create new adapter
ApplicationAdapter adapter = new ApplicationAdapter(this, data);
// set the adapter to list
setListAdapter(adapter);
}
#Override
public void onFetchFailure(String msg) {
// dismiss the progress dialog
if(dialog != null) dialog.dismiss();
// show failure message
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
This is my array adapter:
public class ApplicationAdapter extends ArrayAdapter<Application>{
private List<Application> items;
public ApplicationAdapter(Context context, List<Application> items) {
super(context, R.layout.app_cat_list, items);
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.app_cat_list, null);
}
Application app = items.get(position);
if(app != null) {
TextView titleText = (TextView)v.findViewById(R.id.titleTxt);
if(titleText != null) titleText.setText(app.getTitle());
}
return v;
}
Now I want to click on single row and open another activity passing some values via intent extra.
Where should I implement click listener?
I'm pretty sure it should be inserted in the "getView" but how I pass the app.getTitle() via intent? I know how pass intent extra in general, tried but no click happens.
Any help would be appreciated, thanks
Now I want to click on single row and open another activity passing
some values via intent extra. Where should I implement click listener?
No need to add OnItemClickListener because extending ListActivity in MenuActivity so just override onListItemClick method for handing ListView row click:
#Override
public void onListItemClick(ListView l, View view, int position, long id) {
// your code here...
}
how I pass the app.getTitle() via intent?
Get selected row TextView value in onListItemClick using view parameter:
TextView txtView=(TextView)v.findViewById(R.id.titleTxt);
String selectedText=txtView.getText().toString();
Use selectedText for sending value with Intent in Next Activity
Put this in your getView()
v.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent =new Intent(context, YourActivity.class);
context.startActivity(intent);
}
});
There can be multiple ways and following is one of them:
Set onItemClickListner on your listview in your activity and it will give you a callback i.e onListItemClick. But as you said you want the title their you have to set tag on the convertView in the getView method like covertView.setTag("itemTitle"); and in your onListItemClick get the tag from view and convert it to the title like this v.getTag().toString(); and set it any where you want.
follwoing is the full code:
#Override
public void onListItemClick(ListView l, View view, int position, long id) {
String title = view.getTag().toString();
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("title", title);
startActivity(intent);
// your code here... }
Please post if got stuck anywhere.
Suppose we have a list with several items. Each item has several fragments and a label within. When a user clicks on each label I need to change the text of the button1 that is out of the list view. How can I receive that label click event from inside of the list item and change a view that is out of the list view and list adapter.
I know how to handle internal events of the list view adapter inside the adapter. It's as simple as assigning the event handlers in GetView() method but they are not available out of the list.
Thanks for any help
Solved
I created a custom event and EventAgrs. When user clicks the label I invoke this event and in the main activity I handle the event and change the text of buton1. It was easier than I thought. In GetView() I assign the click event to the label_Click() event handler.
GetView(){
.
.
label.Click += label_Click();
.
.
}
In label_Click() I invoke the custom event that I have implemented before:
private void label_Click()(object sender, EventArgs e)
{
LabelClickedEvent.Invoke(sender, new LabelClickEventArgs("aaa", "bbb"));
}
In the list Adapter I declared this custom event: (For more information please look at this guide)
public event LabelClickedEventHandler LabelClickedEvent;
public delegate void LabelClickedEventHandler(object, sender,LabelClickEventArgs args);
public class LabelClickEventArgs : EventArgs
{
public string param1 { get; set; }
public string param2 { get; set; }
public LabelClickEventArgs(string param1 , string param2 )
{
this.param1 = param1 ;
this.param2 = param2 ;
}
}
In the main activity I simply assigned the event to my event handler and did whatever is needed.
listAdapter.LabelClickedEvent += listAdapter_LabelClickedEvent;
.
.
void listAdapter_LabelClickedEvent(object sender, TheListAdapter.LabelClickEventArgs args)
{
sendButton.Text = args.param1;
}
Hope it helps someone.
I do not know the proper way, but one way to do would be to implement the label item's OnClickListener() in the adapter, pass the reference of Button 1 to your adapter while creating an adapter, and then manipulate button 1 from OnClickListener().
public class MyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList data;
private Button button1;
/************* CustomAdapter Constructor *****************/
public MyAdapter(Activity activity, ArrayList data, Button button1) {
this.data = data;
this.button1 = button1;
this.activity = activity;
inflater = (LayoutInflater) this.activity.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
if (data.size()<=0)
return 1;
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder{
public TextView label1;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
if (convertView==null) {
vi = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.label1 = (TextView)vi.findViewById(R.id.tvLabel1);
holder.label1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
this.button1.setText("Label 1 clicked");
}
});
vi.setTag(holder);
} else {
holder = (ViewHolder)vi.getTag();
}
// show the data in the list view
return vi;
}
}
Suppose you have a button 1 in MainActivity outside list view, so when you create adapter in MainActivity
on your MainActivity's onCreate method do following:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// define and initialize your data
Button button1 = (Button)findViewById(R.id.button1);
MyAdapter adapter = new MyAdapter(this, data, button1);
...
}
Summary: I need a way to trigger my calculate() function within my main activity when an item is added or removed from my ListView
Background:
My android application fills a listview with list items. A list item contains a textview and an imagebutton (delete) that removes the item from the list on click. I use a custom adapter to keep track of changes in the list. This all works fine.
In my main acticity, some calculations take place based on the values in the list in a function called calulate(). I want to call this function whenever an item is added or deleted from the list. However, I don't know if this is possible and how to implement such a function.
I noticed that it is possible to add an observer using registerDataSetObserver() that will be notified when notifyDataSetChanged() is called. However, I'm not sure if this is what I need and how to implement this. Any help or suggestions are more than welcome.
Here is my CustomListAdapter:
public class CustomListAdapter extends BaseAdapter {
static final String TAG = "CustomListAdapter";
private Context context;
ArrayList <String> listArray;
LayoutInflater inflater;
public CustomListAdapter(Context context, List <String> inputArray) {
super();
this.context = context;
this.listArray = (ArrayList<String>) inputArray;
}
#Override
public int getCount() {
return listArray.size(); // total number of elements in the list
}
#Override
public String getItem(int i) {
return listArray.get(i); // single item in the list
}
#Override
public long getItemId(int i) {
return i; // index number
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
View V = convertView;
if(V == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
V = vi.inflate(R.layout.selected_drug_list_item, null);
}
//place text in textview
String listItem = listArray.get(position);
TextView textView = (TextView) V.findViewById(R.id.selectedDrugName);
textView.setText(listItem);
ImageButton deleteSelectedDrugButton = (ImageButton) V.findViewById(R.id.deleteSelectedDrugButton);
deleteSelectedDrugButton.setTag(position);
//Listener for the delete button. Deletes item from list.
deleteSelectedDrugButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
//re
Integer index = (Integer) view.getTag();
listArray.remove(index.intValue());
notifyDataSetChanged();
}
});
return V;
}
public void add(String input) {
listArray.add(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
}
public void remove(String input){
listArray.remove(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
}
}
Here is how my ListView is initialized in my onCreate() method.
selectionListView = (ListView) findViewById(R.id.selectionListView);
selectionAdapter = new CustomListAdapter(this,myListItems);
selectionListView.setAdapter(selectionAdapter);
If any other code fragment is required, I'll happily provide it.
You may create Interfece that will be implemented by Your Main Activity and passed to Adapter (eg. in constructor)
public interface SomeInterface
{
public void foo();
}
Add SomeInterface object in Your Adapter
SomeInterface responder=null;
public CustomListAdapter(Context context, List <String> inputArray, SomeInterface responder) {
super();
this.context = context;
this.listArray = (ArrayList<String>) inputArray;
this.responder=responder;
}
public void add(String input) {
listArray.add(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
responder.foo();
}
public void remove(String input){
listArray.remove(input);
notifyDataSetChanged();
Log.v(TAG, input + " added to list");
responder.foo();
}
and implements SomeInterface in Your MainActivity
public class MainActivity extends Activity implements SomeInterface
{
...
public void foo()
{
//do whatever
}
private initializeAdapter()
{
CustomListAdapter adapter=new Adapter(this, someArray, this);
}
}
You can create a callback interface with a simple method, like stuffHappened(). Then, let your activity implement that interface. Now you can add a constructor argument which has as type the callback interface, pass the activity in, keep it as a member variable on the adapter and call the stuffHappened() method whenever you need to send feedback to your activity.
Practicing on the ListView, I thought of adding buttons as well to it, rather than showing only content. But in my implementation, the button does not do anything at all.
Plus I was confused whether I could get the position of the button clicked. For now I am just sending the toSend declared inside the OnItemClick in an intent.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
final int toSend = position;
TextView refId = (TextView)view.findViewById(R.id.list_id);
TextView refName = (TextView)view.findViewById(R.id.list_name);
TextView refAdd = (TextView)view.findViewById(R.id.list_address);
Button edit = (Button)view.findViewById(R.id.edit);
edit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
Intent i = new Intent(ListActivity.this, EditLayout.class);
i.putExtra("position", toSend);
startActivity(i);
}
});
String sd_id = refId.getText().toString();
String sd_name = refName.getText().toString();
String sd_add = refAdd.getText().toString();
buildAlert(sd_id, sd_name, sd_add);
}
});
You're pretty close. The "inside" setOnClickListener needs to happen when you create the list row view (the view containing id, name, address, edit).
You can do that during getView(). But where to send the clicks? Instead of creating a new onClickListener, use "this" (your activity). Put an onClick() handler in the activity.
Then, when you get a click, the onClick method will execute. Next problem: how do you know which row clicked? The easiest way that comes to mind is to give the button a different id for e ach row - use the row index (you might need to start at 1 rather than 0 - be warned).
Finally, given the row id, it's easy to start your "nested" activity.
Hope this helps.
(added later)
I do it like this; you'll need to define a layout for your row view:
class MyActivity extends Activity implements View.OnClickListener
{
public void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView (R.layout.my_page);
ListView list = (ListView)findViewById (android.R.id.list);
MyArrayAdapter adapter = new MyArrayAdapter (this, <your array of data>);
list.setAdapter (adapter);
}
#Override
public void onClick(View v)
{
int buttonId = v.getId();
if (buttonId is within range)
... do what you need to do with the click ...
}
private class MyArrayAdapter extends ArrayAdapter<MyData>
{
private Activity act;
//-----------------------------------------------------------------------------
public MyArrayAdapter (Activity act, MyData array)
{
super (act, R.layout.list_row, array);
this.act = act;
}
//-----------------------------------------------------------------------------
#Override
public View getView (int position, View convertView, ViewGroup parent)
{
ViewGroup rowView = (ViewGroup)convertView;
if (rowView == null)
{
LayoutInflater inflater = act.getLayoutInflater();
rowView = (ViewGroup) inflater.inflate (R.layout.list_row,
parent, false);
}
Button button = (Button)rowView.findViewById (R.id.is_member);
button.setId (position+1); // add one to avoid 0 as an id.
button.setOnClickListener (act);
// set field values here -- not shown
return rowView;
}
}
}