I have a ListView with custom adapter with Image. I also have sound assigned to each item in ListView. I want when user for example click on 3rd item in ListView to change image of that item, and when user click on for example 15th item, to change item 3 image to old one, and change image of item 15 And so on. How can I do that?
This is my code:
Adapter:
#Override
public View getView(final int position, View convertView, ViewGroup parent){
View item=convertView;
HolderActivity holder=null;
if(item==null){
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
item=inflater.inflate(R.layout.generator, parent,false);
holder=new HolderActivity(item);
item.setTag(holder);
}
else{
holder=(HolderActivity)item.getTag();
}
holder.transfer.setImageResource(transfer[position]);
holder.myImage.setImageResource(pictures[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
return item;
}
}
And then simple ItemClickListener in Main Activity
int[] songPos = { R.raw.position1, R.raw.position2, R.raw.position3,
R.raw.position4, R.raw.position4, R.raw.position5, R.raw.position6...etc etc
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View paramAnonymousView, int position, long id) {
CentralActivity.this.playSound(position);
}
});
private void playSound(int paramInt)
{
try
{
if ((CentralActivity.playing.booleanValue()) && (CentralActivity.position == paramInt))
{
Toast.makeText(CentralActivity.this, "It's Playing", Toast.LENGTH_SHORT).show();
}
else
{
CentralActivity.mp = MediaPlayer.create(CentralActivity.this, Integer.valueOf(this.songPos[paramInt]).intValue());
CentralActivity.mp.start();
CentralActivity.position = paramInt;
CentralActivity.playing = Boolean.valueOf(true);
CentralActivity.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
public void onCompletion(MediaPlayer paramAnonymousMediaPlayer)
{
paramAnonymousMediaPlayer.release();
CentralActivity.playing = Boolean.valueOf(false);
}
});
}
}
catch (Exception localException) {}
}
Here are pieces for your code which should work:
Activity:
private ArrayAdapter mAdapter; // Make the mAdapter reachable by other methods
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// If creating adapter from your activity, send it's context (this):
mAdapter = new ArrayAdapter(this,...);
...
}
private void playSound(int paramInt) {
try {
if ((CentralActivity.playing) && (CentralActivity.position == paramInt)) {
Toast.makeText(CentralActivity.this, "It's Playing", Toast.LENGTH_SHORT).show();
} else {
// Set activity variables
CentralActivity.position = paramInt;
CentralActivity.playing = true;
// Update ListView views
mAdapter.notifyDataSetChanged();
// Create MP and start playing
CentralActivity.mp = MediaPlayer.create(CentralActivity.this, Integer.valueOf(this.songPos[paramInt]).intValue());
CentralActivity.mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer paramAnonymousMediaPlayer) {
paramAnonymousMediaPlayer.release();
CentralActivity.playing = false;
// Update ListView views
mAdapter.notifyDataSetChanged();
}
});
CentralActivity.mp.start();
}
} catch (Exception localException) {
localException.printStackTrace();
}
}
Adapter:
public class CustomAdapter extends ArrayAdapter {
// Considering CentralActivity is the name of your Activity's class
private CentralActivity mActivity;
// Custom adapter's constructor
public CustomAdapter(Context context, ...) {
mActivity = (CentralActivity) context;
...
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View item = convertView;
HolderActivity holder = null;
if (item == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
item = inflater.inflate(R.layout.generator, parent, false);
holder = new HolderActivity(item);
item.setTag(holder);
} else {
holder = (HolderActivity) item.getTag();
}
if (mActivity.playing && mActivity.position == position) {
holder.myImage.setImageResource(pauseImageResource);
} else {
holder.myImage.setImageResource(pictures[position]);
}
holder.transfer.setImageResource(transfer[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
return item;
}
...
}
Note that you will obviously need to replace ... and maybe CentralActivity too, to corresponding equivalents in your code.
The idea is to keep track of which index is playing.
Create setter in your adapter class:
public void setPlayingIndex(int index){
mPlayingIndex = index;
if(mPlayingIndex != ListView.INVALID_POSITION){
notifyDataSetChanged();
}
}
Make sure you call this method when you play the sound, like:
mListAdapter.setPlayingIndex(index);
In your getView() method, besides the ViewHolder pattern code have this:
if(mPlayingIndex == position){
//add the playing image
}else{
// load normal
holder.transfer.setImageResource(transfer[position]);
holder.myImage.setImageResource(pictures[position]);
holder.ringName.setText(ringNames[position]);
holder.ringDesc.setText(descInfo[position]);
}
Related
I'm using view pager with swiping tab layouts. And i'm displaying list view of data using custom adapter. And also onclick of list view i have a list view detail activity where I'm displaying data in more detail. In these detail activity i'm performing some changes to the data(some post method). after that I create an instance of customAdapter class and call notifyDataSetChanged() in order to refresh list view. My problem over here is the list view some times refreshes quickly and some times there is a delay of some seconds.
So, Can somebody suggest me proper usage of list view and what changes needs to be done in order to refresh list view whenever a post method is performed.
My code Fragment class:
private void showJsonData(String response) {
try {
String serviceID = LoggedInUserStore.getLoggedInServiceId(getContext());
List<Complaint> userList = new ArrayList<>(); //ArrayList of type user(POJO CLASS)
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
if (serviceID.equals(jsonArray.getJSONObject(i).getString("ServiceID"))) {
if (jsonArray.getJSONObject(i).getString("CallStatusID").equalsIgnoreCase("1")) {
userList.add(0, Complaint.fromJson(jsonArray.getJSONObject(i))); //
}
}
}
assignAdapter = new AssignAdapter(getActivity(), userList);
listView.setAdapter(assignAdapter);
listView.invalidateViews();
assignAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
My custom adapter class
public class AssignAdapter extends BaseAdapter implements Filterable {
List<Complaint> ticket = new ArrayList<>();
private Context context;
String ticketNo, complaint, raiseDate;
Complaint user;
List<Complaint> temporaryList = new ArrayList<>();
/*String status, priority;*/
public AssignAdapter(Context context, List<Complaint> ticket) {
this.context = context;
this.ticket = ticket;
this.temporaryList = ticket;
}
#Override
public int getCount() {
return temporaryList.size();
}
#Override
public Object getItem(int position) {
return temporaryList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public class viewHolderItem {
TextView ticketNumberText, complaintNameText, raisedDateText;
}
//Set the layout for the fragment and return it.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
viewHolderItem holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.custom_list_view, null, true);
holder = new viewHolderItem();
holder.ticketNumberText = (TextView) convertView.findViewById(R.id.ticketIdSupervisor);
holder.complaintNameText = (TextView) convertView.findViewById(R.id.complaintNameSupervisor);
convertView.setTag(holder);
} else {
holder = (viewHolderItem) convertView.getTag();
}
user = temporaryList.get(position);
if (user != null) {
//Get the Ticket Number
Typeface custom_font = Typeface.createFromAsset(context.getAssets(), "fonts/DroidSerif.ttf");
ticketNo = temporaryList.get(position).getTicketNumber();
holder.ticketNumberText.setText(ticketNo);
holder.ticketNumberText.setTag("ticketNumber");
holder.ticketNumberText.setTypeface(custom_font);
//Get the complaint Name
complaint = temporaryList.get(position).getComplaintDetails();
holder.complaintNameText.setText(complaint);
holder.complaintNameText.setTag("complaint");
holder.complaintNameText.setTypeface(custom_font);
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context.getApplicationContext(), ComplaintDetailsSupervisor.class);
i.putExtra("COMPLAINT NAME", temporaryList.get(position).getComplaintDetails());
i.putExtra("RAISED DATE", temporaryList.get(position).getRaisedDate().substring(0, 10));
context.startActivity(i);
}
});
notifyDataSetChanged();
return convertView;
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
My List view detail activity class
dialogButtonOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
assignComplaint();
al.remove(position);
AssignAdapter assignAdapter = new AssignAdapter(getApplicationContext(), al);
assignAdapter.notifyDataSetChanged();
ComplaintDetailsSupervisor.this.finish();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
dialogButtonNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
}
});
}
public void assignComplaint() throws JSONException {
//my custom method...
}
In the list view detail activity class i'm doing this
al.remove(position);
AssignAdapter assignAdapter = new AssignAdapter(getApplicationContext(), al);
assignAdapter.notifyDataSetChanged();
ComplaintDetailsSupervisor.this.finish();
Removing the position of list view and immediately calling adapter. This works fine but I don't know why sometimes it does not refreshes..May be when list view has a single item it does not refreshes immediately.
You are creating a new adapter and calling notifyDatasetChanged on it but have not called setAdapter with the new adapter as a parameter, hence why your list ist not refreshed.
You need to call
setAdapter(assignAdapter)
or reuse your existing assignAdapter and then call notifyDatasetChanged() on it.
I have a ListView that is within a Fragment. In the onCreateView section I have set a onItemClickListener for the list, which highlights the selected item in the ListView. I have set two ImageButtons that navigate up and down the list. On selection a new Row is inflated that has its TextView's set to the content of the select item (for the purpose of retaining the highlighted selected state). However I am having difficulty adding that item back to the list. The app will not compile due to the line routines.add(selectedPos-1, str); it wants wants int location, Routine object. I believe the issue is with my construction of my SelectedAdapter class, but I have been unable to determine what to change/pass with regard to the Object.
IE:
public SelectedAdapter(Context context, int textViewResourceId,List objects) {
super(getActivity(), R.layout.listview_routines, routines); }
I would greatly appreciate any input as how to correct this issue; as well as any advice if there is a better way to maintain a selected state. Thanks for your help.
Fragment:
public static class FragmentRoutine extends Fragment {
DatabaseHandler db;
private ListView routineListView;
private List<Routine> routines = new ArrayList<Routine>();
ArrayAdapter<Routine> routineAdapter;
Routine longClickedItemRoutines;
private SelectedAdapter selectedAdapter;
public FragmentRoutine() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.routines,
container, false);
db = new DatabaseHandler(getActivity().getApplicationContext());
routineListView = (ListView) rootView.findViewById(R.id.routineList);
registerForContextMenu(routineListView);
db.closeDB();
if (db.getExerciseCount() != 0)
routines.clear();
routines.addAll(db.getAllRoutines());
populateList();
selectedAdapter = new SelectedAdapter(this.getActivity(), 0, routines);
selectedAdapter.setNotifyOnChange(true);
routineListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickedItemRoutines = routines.get(position);
return false;
}
});
routineListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView arg0, View view,
int position, long id) {
selectedAdapter.setSelectedPosition(position);
}
});
routineListView.post(new Runnable() {
#Override
public void run() {
routineListView.setItemChecked(0, true);
}
});
// move up event handler
ImageButton btnMoveUp = (ImageButton) rootView.findViewById(R.id.btnMoveUp);
btnMoveUp.setOnClickListener(new AdapterView.OnClickListener() {
public void onClick(View arg0) {
moveUp();
}
});
// move down event handler
ImageButton btnMoveDown = (ImageButton) rootView.findViewById(R.id.btnMoveDown);
btnMoveDown.setOnClickListener(new AdapterView.OnClickListener() {
public void onClick(View arg0) {
moveDown();
}
});
setHasOptionsMenu(true);
return rootView;
}
// Move selected item "up" in the ViewList.
private void moveUp(){
Routine currentToDoSave = routines.get(selectedAdapter.getSelectedPosition());
int selectedPos = selectedAdapter.getSelectedPosition();
if (selectedPos > 0 ){
routines.remove(selectedPos);
String str = currentToDoSave.getTagName();
//Problem Line Below
routines.add(selectedPos-1, str);
// set selected position in the adapter
selectedAdapter.setSelectedPosition(selectedPos-1);
}
}
// Move selected item "down" in the ViewList.
private void moveDown(){
Routine currentToDoSave = routines.get(selectedAdapter.getSelectedPosition());
int selectedPos = selectedAdapter.getSelectedPosition();
if (selectedPos < routines.size()-1 ){
routines.remove(selectedPos);
String str = currentToDoSave.getTagName();
routines.add(selectedPos+1, str);
// set selected position in the adapter
selectedAdapter.setSelectedPosition(selectedPos+1);
}
}
public class SelectedAdapter extends ArrayAdapter<Routine>{
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
public SelectedAdapter(Context context, int textViewResourceId,
List objects) {
super(getActivity(), R.layout.listview_routines, routines);
}
public void setSelectedPosition(int pos){
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition(){
return selectedPos;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
// only inflate the view if it's null
if (v == null) {
LayoutInflater vi
= (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.selected_row, null);
}
// get text view
TextView label = (TextView)v.findViewById(R.id.txtExample);
// change the row color based on selected state
if(selectedPos == position){
label.setBackgroundColor(Color.CYAN);
}else{
label.setBackgroundColor(Color.WHITE);
}
label.setText(this.getItem(position).toString());
return(v);
}
}
private void populateList() {
routineAdapter = new SaveListAdapterT();
routineListView.setAdapter(routineAdapter);
}
public class SaveListAdapterT extends ArrayAdapter<Routine> {
public SaveListAdapterT() {
super(getActivity(), R.layout.listview_routines, routines);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null)
view = getActivity().getLayoutInflater().inflate(R.layout.listview_routines, parent, false);
Routine currentToDoSave = routines.get(position);
TextView name = (TextView) view.findViewById(R.id.name);
name.setText(currentToDoSave.getTagName());
return view;
}
}
}
I'm trying to make a ListFragment. I looked the Api Demo (FragmentLayout). it works on a simple example and now i want to apply it to my existing project.
Here is my code. I create inner classes (RecipeList & RecipeDetail) as in the Api Demo.
public class InfoActivity extends MenuActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info_fragment_layout);
// ...
}
public static class RecipeList extends ListFragment {
private int mCurrentSelectedItemIndex = -1;
private boolean mIsTablet = false;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
accountData = new ArrayList<Account>();
new AccountSyncTask() {
#Override
public void onPostExecute(
final ArrayList<ArrayList<String>> result) {
// For each retrieved account
Bd.insert(retrievedAccount);
accountData.add(retrievedAccount);
}
accountListAdapter = new AccountListAdapter(
InfoActivity.this, R.layout.accountlist_detail,
accountData);
accountListAdapter = new AccountListAdapter(
activityContext, R.layout.accountlist_detail,
accountData);
setListAdapter(accountListAdapter);
}
}.execute(sessionName, null, "getAllObjectOnServer",
String.valueOf(nbRow));
if (savedInstanceState != null) {
mCurrentSelectedItemIndex = savedInstanceState.getInt(
"currentListIndex", -1);
}
// This is a tablet if this view exists
View recipeDetails = getActivity()
.findViewById(R.id.recipe_details);
mIsTablet = recipeDetails != null
&& recipeDetails.getVisibility() == View.VISIBLE;
if (mIsTablet) {
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
if (mIsTablet && mCurrentSelectedItemIndex != -1) {
showRecipeDetails();
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCurrentSelectedItemIndex = position;
showRecipeDetails();
}
private void showRecipeDetails() {
if (mIsTablet) {
// Set the list item as checked
getListView().setItemChecked(mCurrentSelectedItemIndex, true);
// Get the fragment instance
RecipeDetail details = (RecipeDetail) getFragmentManager()
.findFragmentById(R.id.recipe_details);
// Is the current visible recipe the same as the clicked? If so,
// there is no need to update
if (details == null
|| details.getRecipeIndex() != mCurrentSelectedItemIndex) {
details = RecipeDetail
.newInstance(mCurrentSelectedItemIndex);
FragmentTransaction ft = getFragmentManager()
.beginTransaction();
ft.replace(R.id.recipe_details, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else {
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentListIndex", mCurrentSelectedItemIndex);
}
}
public static class RecipeDetail extends Fragment {
private int mRecipeIndex;
public static RecipeDetail newInstance(int recipeIndex) {
// Create a new fragment instance
RecipeDetail detail = new RecipeDetail();
// Set the recipe index
detail.setRecipeIndex(recipeIndex);
return detail;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
View v = inflater
.inflate(R.layout.recipe_details, container, false);
//..
return v;
}
public int getRecipeIndex() {
return mRecipeIndex;
}
public void setRecipeIndex(int index) {
mRecipeIndex = index;
}
}
I have a custom ArrayAdapter (my items in the ListFragment contain 4 textViews and a clickable imageButton).
AccountListAdapter :
public class AccountListAdapter extends ArrayAdapter<Account> {
private final Context context;
private final int layoutResourceId;
private final ArrayList<Account> data;
public AccountListAdapter(Context context, int layoutResourceId,
ArrayList<Account> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
AccountHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
holder = new AccountHolder();
convertView.setClickable(true);
convertView.setFocusable(true);
holder.txtName = (TextView) convertView.findViewById(R.id.nom);
holder.txtId = (TextView) convertView.findViewById(R.id.id);
convertView.setTag(holder);
} else {
holder = (AccountHolder) convertView.getTag();
}
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("click", "index = " + position);
}
});
holder.txtName.setText(data.get(position).getName());
holder.txtId.setText(data.get(position).getId());
convertView.setBackgroundResource(R.drawable.list_selector);
ImageButton img = (ImageButton) convertView.findViewById(R.id.check);
img.setTag(position);
return convertView;
}
static class AccountHolder {
TextView txtName;
TextView txtId;
}
}
Problem :
When i click on an Item of the listFragment,
public void onListItemClick(ListView l, View v, int position, long id) {
mCurrentSelectedItemIndex = position;
Log.i("click", "here";
showRecipeDetails();
}
is not called but the listener on an item defined in AccountListAdapter works
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.i("click", "index = " + position);
}
});
Why is onListitemClick never called ?
Another question : is it a proper way to consume a web service in another thread in the onActivityCreated function of my ListFragment (in order to populate the list) ?
Thx in advance
EDIT = For the moment i made "showRecipeDetails" static and call it in the listener in my custom ArrayAdapter.
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
RecipeList.showRecipeDetails(position);
}}
I'm not satisfied with my solution, i'm interessed to any other solution
OnItemClickListeners must first be associated with the ListView you want to record clicks for. In your onActivityCreated(..) method, place getListView().setOnItemClickListener(this) somewhere and put implements OnItemClickListener after public static class RecipeList extends ListFragment.
I have a Spinner on my Activity. I use an ArrayList and a custom SpinnerAdapter to populate the list that pops up when the Spinner is pressed.
My problem is the way the Spinner looks on the Activity when it is not pressed. It is all gray. No text is visible. Even after I press the spinner and then choose an item from the resulting list, the Spinner does not populate with text.
Also, when I select an item from the Spinner and then print the selected item position, it prints -1. Many have commented that there is no list of data attached to my spinner, but there obviously is. How else could I press on the Spinner and then choose from a resulting list?
// This sets up the adapter and the arraylist that contains the data
private void setUpAdapter() {
mData = new ArrayList<MyData>();
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
// this populates the arraylist that is attached to the spinner's adapter
// it is called once an AsyncTask finishes pulling data from a local database
private void populateSpinner(ArrayList<MyData> result) {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mSpinner.setSelected(0);
}
}
// this is the adapter for the spinner
private class MyAdapter implements SpinnerAdapter {
ArrayList<MyData> data;
public MyAdapter(ArrayList<MyData> data){
this.data = data;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return android.R.layout.simple_spinner_dropdown_item;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(getApplicationContext());
v.setTextColor(Color.BLACK);
v.setText(data.get(position).getName());
v.setPadding(0, 20, 0, 20);
return v;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return this.getView(position, convertView, parent);
}
}
<Spinner
android:id="#+id/my_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
When I select an item from the Spinner and then print the selected item position, it prints -1
This is because you are referencing BLANK list
mData = new ArrayList<MyData>();
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
Set spinner adapter in onPostExecute() of AsynTask.
#Override
protected void onPreExecute() {
mData = new ArrayList<MyData>();
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
//gets "result" to fill mData
return null;
}
#Override
protected void onPostExecute(Void result) {
setUpAdapter();
}
private void setUpAdapter() {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
mSpinner.setSelected(0);
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
}
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
Use Activity context instead of the Application context for your spinner. See documentation of getApplicationContext() api to understand its proper usage.
Pass the activity context to MyAdapter and use it in creating the TextView's in getView callback.
mAdapter = new MyAdapter(mData, this); // this is activity context.
In MyAdapter :
public MyAdapter(ArrayList<MyData> data, Context context){
this.data = data;
mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView v = new TextView(mContext);
v.setTextColor(Color.BLACK);
v.setBackgroundColor(Color.WHITE);
v.setText(data.get(position).getName());
v.setPadding(0, 20, 0, 20);
return v;
}
You can set static sizes using the xml attribute android:layout_height.
Using dp unit instead of px is recommended for multiple screen compatibility.
As for the text, try to use android:prompt attribute in your Spinner xml. For the color I'm guessing it's like other widgets, just use android:textColor
THIS code is WORKING, the spinner correctly display the field, however i must say maybe it is not 100% perfect, cause for some reason im unable to leave blank the initial value of the field, it has by default the value of item 0.
package com.cccheck;
public class OneCheckActivity extends Activity {
LayoutInflater factory;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.spinner_view);
ArrayList tdata = new ArrayList<MyData>();
MyData mdata =new MyData();
mdata.setName("");
mdata.setData("-1");
MyData ndata =new MyData();
ndata.setName("ciao belluzzo");
ndata.setData("1");
tdata.add(mdata);
tdata.add(ndata);
mdata= new MyData();
mdata.setName("vai alla fnac");
mdata.setData("2");
tdata.add(mdata);
mSpinner = (Spinner) findViewById(R.id.my_spinner);
factory = LayoutInflater.from(this);
populateSpinner(tdata);
setUpAdapter();
mSpinner.setSelected(false);
try {
mAdapter.notify();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//mAdapter.registerDataSetObserver(new MyObserver());
}
ArrayList<MyData> mData;
MyAdapter mAdapter = new MyAdapter(null);
Spinner mSpinner;
// This sets up the adapter and the arraylist that contains the data
private void setUpAdapter() {
mSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
MyData g = (MyData) parent.getItemAtPosition(pos);
// TODO
Toast.makeText(OneCheckActivity.this , "selected item : " + pos + ", value: " + g.getData(),Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
});
}
// this populates the arraylist that is attached to the spinner's adapter
//it is called once an AsyncTask finishes pulling data from a local database
private void populateSpinner(ArrayList<MyData> result) {
if (result != null) {
if (mData == null) {
mData = new ArrayList<MyData>();
}
else {
mData.clear();
}
for (int index = 0; index < result.size(); index++) {
mData.add(result.get(index));
}
mAdapter = new MyAdapter(mData);
mSpinner.setAdapter(mAdapter);
}
}
// this is the adapter for the spinner
private class MyAdapter implements SpinnerAdapter {
ArrayList<MyData> data;
public MyAdapter(ArrayList<MyData> data){
this.data = data;
}
public void updateData(ArrayList<MyData> data){
this.data = data;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return android.R.layout.simple_spinner_dropdown_item;
}
#Override
public LinearLayout getView(int position, View convertView, ViewGroup parent) {
LinearLayout pv = (LinearLayout)(factory.inflate(R.layout.spinner_item, null));
TextView tv = (TextView) pv.findViewById(R.id.textviewid);
tv.setTextColor(Color.BLACK);
MyData item = data.get(position);
tv.setText( item.getName() + " - " + item.getData() + " ");
tv.setPadding(0, 20, 0, 20);
return pv;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return data.isEmpty();
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// TODO Auto-generated method stub
}
#Override
public LinearLayout getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView instanceof LinearLayout) System.out.println("%%%%%%%%%%%%%%55555 hai ragione");
return this.getView(position, convertView, parent);
}
}
}
use this as layout for spinner_item.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="28px"
android:id="#+id/textviewid"
/>
</LinearLayout>
I have a list activity which has a list showing results of a query. Well I want to be able to click on each item and the item changes color but it doesn't work. I want the item to remain selecetd state untill "accepte" button is pressed or item is pressed again. I know that is how text boxes work but i prefer to do it my own way.
Here is my code:
public void createList() {
if (ok == 1) {
//hay muachas possibilidades
if (sol.get(i).getMultiseleccion() != 0){
bt2.setVisibility(View.INVISIBLE);
}else {
//solo se clika en una
//lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
bt2.setVisibility(View.VISIBLE);
}
String hd1 = sol.get(i).getDescSolicitud();
tv2.setText(hd1);
ArrayList<SubSolicitud> sub = sol.get(i).getSubSol();
mAdapter = new EventAdapter(this, sub);
setListAdapter(mAdapter);
lv.setTextFilterEnabled(true);
lv.computeScroll();
lv.setDividerHeight(1);
lv.setItemsCanFocus(false);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
ok = 1;
//OnListClick(position, arg1);
if (sol.get(i).getMultiseleccion() != 0) {
// multiples respuestas
((EventEntryView)arg1).text1.setTextColor(Color.YELLOW);
guardarRespuesta();
}else {
buscarElementos();
}
}
});
}
// informar el usuario de que hay un error
else
buildAlertDialog();
}
and the other classes are:
public class EventAdapter extends BaseAdapter {
public ArrayList<SubSolicitud> mEvents = null;
public EventAdapter(Context c, ArrayList<SubSolicitud> subsol) {
mContext = c;
mEvents = subsol;
}
public int getCount() {
return mEvents.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
EventEntryView btv;
if (convertView == null) {
btv = new EventEntryView(mContext, mEvents.get(position));
} else {
btv = (EventEntryView) convertView;
String title1 = mEvents.get(position).getDescripcion();
if (title1 != null) {
btv.setText1Title(title1);
}
}
btv.setBackgroundColor(Color.BLACK);
return btv;
}
private Context mContext;
public void clearEvents() {
mEvents.clear();
notifyDataSetChanged();
}
public void addEvent(SubSolicitud e) {
mEvents.add(e);
}
}
public class EventEntryView extends LinearLayout {
// private View inflatedView;
private TextView text1;
// private TextView text2;
public EventEntryView(Context context, SubSolicitud subSolicitud) {
super(context);
this.setOrientation(VERTICAL);
text1=new TextView(context);
text1.setTextSize(20);
text1.setPadding(10, 10, 10, 10);
text1.setTextColor(Color.WHITE);
String t = subSolicitud.getDescripcion();
text1.setText(t);
addView(text1, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
public void setText1Title(String title1) {
// TODO Auto-generated method stub
text1.setText(title1);
}
}
As you can see I try to get the text in yellow but it doesn't work I click and it doesn't become yellow.
Is there a solution?
thanks
It doesn't work because there is not an EventEntryView for each item in the list - the same EventEntryView is reused to render each.
You need to add something on your SubSolicitud model object to indicate it's been selected (let's say a boolean "selected" property).
In your onItemClicked handler you would toggle this property -
public void onItemClick(AdapterView<?> adapterView, View view,
int position, long id) {
// ...
SubSolicitud selectedSubSol = (SubSolicitud)adapterView.getAdapter().getItem(id);
boolean currentValue = selectedSubSol.isSelected();
selectedSubSol.setSelected(!currentValue); // toggle 'selected' on and off
// ...
}
(You also need to fix your EventAdapter getItem method to return mEvents.get(position) for this to work...)
Then in your EventAdapter getView method, you use the value of the "selected" property to render the text color -
public View getView(int position, View convertView, ViewGroup parent) {
// ...
if (mEvents.get(position).isSelected()) {
btv.text1.setTextColor(Color.YELLOW);
} else {
// you have to have an else to set it back to the default
// color, because the view is reused for all list items.
btv.text1.setTextColor(Color.WHITE);
}
// ...
}
This is how you change the color.
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
position = position - listView.getFirstVisibleItem();
((EditText)arg0.getChildAt(position).findViewById(R.id.myTextView)).setTextColor(Color.YELLOW);
}
But if you want to release the item from the color you should iterate through each item of the listview and change it back to normal or you can do it inside the getView() since it is called every time there is action on the listview