Different content for each Spinner item in the same Activity - android

How can I show different content after selecting an item from the Spinner?
I want to create a Spinner with locations of chain stores.

I want the spinner to be always there on top. The only thing that
changes to be the content under the spinner
Create a simple method in your activity to refresh the layout below the Spinner(which will remain untouched). That method will be called from a OnItemSelectedListener set on the Spinner. It would be something like this:
private void changeAdress(int newSelectedAdress) {
// The ImageView and the TextView will be already in the layout
ImageView map = (ImageView) findViewById(R.id.theIdOfTheImage);
// Set the image. You know the current address selected by the user
// (the newSelectedAddress int) so get it from the array/list/database
// where you stored it
// also set the image
}
Called the method above from the onItemSelected callback:
yourSpinnerRefference.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
changeAddress(position);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
If this is not what you want, please explain.
Edit: Make two arrays to hold your data:
int[] images = {R.drawable.imag1, R.drawable.imag2 ..etc...};
//also for the text
String[] text = {"text1", "text2 ...etc...};
Then use those two arrays in the method I recommended above:
private void changeAdress(int newSelectedAddress) {
((ImageView)findViewById(R.id.mapView1)).setImageResource(images[newSelectedAddress]);
// assing an id to the TextView in your layout and do the same as above.
}
There is no need for multiple ImageView and TextViews.

Related

How to setOnItemSelectedListener on several Dynamically created spinners

I have an Activity where I need to create 1 or more spinners dynamically according to an external DB.
SOme of this spinner items have to show a dialog according what value does the spinner has. For example the spinner has this options:
-Own
-Rental
-Family House
If the user selects Rental I have to show a dialog (or anything) asking him how much does he pays per month. If he selects own, or family nothing should happen.
After I create the layout with the spinners, edittexts, etc. Im using something like this:
for(int q=0;q<=parent.getChildCount();q++){
View v = parent.getChildAt(q);
if (v instanceof Spinner) {
Spinner res = (Spinner) v;
res.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//Here its supposed to show dialog if the option is "RENT"
}
public void onNothingSelected(AdapterView<?> adapterView) {
return;
}
});
}
}
The problem is that when I do this the "setOnItemSelectedListener" only sets for the last spinner on the layout.
How can I do what Im trying? I dont know what else to do.
The easiest solution would probably be to make one Listener as a variable and use that for all of your spinners. To do this, you would not set it as you are currently (using the anonymous inner-class style) and instead would do this:
//This goes outside of the method
private AdapterView.OnItemSelectedListener listener =
new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
System.out.println("Spinner Selected ID = " + parent.getId());
/*
Put a check here for which one is being selected.
While you could use the parent to check, in your case, it will be easier
to use something from your DB table as a unique identifier (maybe a column
name would be ideal? Your pick)
*/
//Show your dialogs here
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
return;
}
};
//This is the method you have where you are iterating the parent object
private void doStuff(){
for(int q=0;q<=parent.getChildCount();q++){
View v = parent.getChildAt(q);
if (v instanceof Spinner) {
Spinner res = (Spinner) v;
res.setOnItemSelectedListener(listener);
}
}
}
Good luck to ya!

Android: setImageResource in adapter changing image 3 positions later

I am using AndroidSwipeableCardStack to do a tinder like interface with a 5 star rating system. When I click on a button that is meant to change the image. The image changes three cards later not in the current card.
This is the project I used: https://github.com/wenchaojiang/AndroidSwipeableCardStack
I assume it is to do with it pre-loading the next card as a recyclerview normally does but I am really not sure.
This my adapter below, you can see at the bottom I call setimageresource on the one star rating image button onclicklistner. I set a Log.d and the button click is registering immediately upon click but the change in the image resource appears only after 3 cards have been swiped.
Edit: So I noticed that regardless of the project I imported, my adapter is only extending ArrayAdatper. So I guessed that the problem might be in the getView method and that I might need to override something else (not sure). But the important point, I checked the position in getView by logging the position and sure enough it said position 0,1,2,3 without anything being swiped away. This is analogous to the offset of the setImageResource so I believe they are interlinked but unfortunately that doesn't bring me any closer to an answer.
Thanks for your help.
public class SongPreviewCardsDataAdapter extends ArrayAdapter<SongDatabaseMappingAdapter> {
public SongPreviewCardsDataAdapter(Context context, int resource) {
super(context, resource);
}
ImageButton oneStarRating;
#Override
public View getView(int position, final View contentView, ViewGroup parent) {
// Initialise Song Views
SongDatabaseMappingAdapter item = getItem(position);
TextView songName = (TextView) (contentView.findViewById(R.id.songNameTextView));
songName.setText(item.getSongTitle());
com.mikhaellopez.circularimageview.CircularImageView songImage = (CircularImageView) contentView.findViewById(R.id.songImageView);
String ImageURL = (item.getPictureURL());
Picasso
.with(this.getContext())
.load(ImageURL)
.into(songImage);
// Initialise Rating Buttons
oneStarRating = (ImageButton) contentView.findViewById(R.id.ratingButton1);
// Create OnClickListners for Ratings Buttons
oneStarRating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
oneStarRating.setImageResource(R.drawable.starfull);
Log.d("Star", "Star Clicked");
}
});
return contentView;
}
}
getView can be called at any time on any item, so if you want something to stay set on a view, you have to model it.
I don't know if your SongDatabaseMappingAdapter class is something you can change or not, but I'll assume you can change it.
Add a variable to your item class, like boolean mOneStar. Getter/setter left as an exercise for the reader.
In getView() make your item final so you can refer to it in the onClick callback:
final SongDatabaseMappingAdapter item = getItem(position);
Use the variable in getView to set up your view:
oneStarRating = (ImageButton) contentView.findViewById(R.id.ratingButton1);
oneStarRating.setImageDrawable(null); // clear out recycled value
if (item.isOneStar()) {
oneStarRating.setImageResource(R.drawable.starfull);
}
In your OnClickListener, set the property on the item and call notifyDataSetChanged():
oneStarRating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Star", "Star Clicked");
item.setOneStar(true);
notifyDataSetChanged();
}
});
The main point is: Never change a view from an event handler. Always change the item from the event handler then call adapter.notifyDataSetChanged(), and always change your view in getView() based on the item.

Binding listeners of spinners added programmatically to the same function

I have a form that for every filter added a new spinner is created with the same options every time. The functionality when selecting an item from the spinner is the same for every spinner, so I was thinking of how to bind the onItemSelected to the same function for every spinner I create.
My solution is to set the listener as I would usually do and call my function with the arguments of the overridden onItemSelected. Is this correct, or is there another way?
// Fix the width of the spinner so it doesn't get resized when making selections.
// Get the screen width and subtract the width of the button next to the spinner.
originalAttributeSelector = (Spinner) findViewById(R.id.attributeSelector0);
originalAttributeSelector.getLayoutParams().width = displayWidth - originalOperatorSelector.getWidth();
// Create the adapter containing the list of choices for the spinner (as well the style for it)
// and bind it to the spinner.
ArrayAdapter<String> attributeSpinnerAdapter =
new ArrayAdapter<>(this, R.layout.spinner_item_material_ref, filterAttributes);
attributeSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
originalAttributeSelector.setAdapter(attributeSpinnerAdapter);
originalAttributeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
// This is implemented somewhere else in the class
myOwnSharedOnItemSelected(parent, view, posiiton, id);
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
}
});

Android Listview.getChildAt() points to two items

I have an activity that has a single listview in it with enough items to extend of the page.
I want to set a certain listView item at position i to a different drawable.
To go this I use the line of code..
listView.getChildAt(selector).setBackgroundResource(R.drawable.main_button_shape_pressed);
There is a very confusing problem going in. This line of code is setting two listView items to the specified drawable.
When i = 0 item 0 and item 11 are set to that drawable. It turns out that when I call this line of code with i both item i and item i+11 are set to that drawable. This is rather baffling. Then to mix EVERYTHING when I start the activity in landscape, it is a different second listview that gets set to that drawable. And in certain scenarios when I change from portrait to landscape, the current highlight listview item on screen will change to a different one.
WTF is going on with the listview class? Are the indexes to it children constantly pointing to different things?
Here is my entire activity.
public class SelectorActivity extends Activity {
private ListView listView;
private int selector;
private boolean set;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.selector_layout);
set=false;
Bundle extras = getIntent().getExtras();
if(extras!=null)
{
selector=extras.getInt("selector");
}
listView=(ListView)findViewById(R.id.selector_layout);
//set the string array for the listview
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.sounds_array, android.R.layout.simple_list_item_1);
adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
listView.setBackgroundResource(R.drawable.listview_background);
listView.setAdapter(adapter);
highlightSelected();
}
//this method will highlight a selected listview once that listview is drawn
private void highlightSelected()
{
if(!set)
{
new Thread(
new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
boolean trigger=true;
while(trigger)
{
if(listView.getChildAt(selector)!=null)
{
set=true;
trigger=false;
listView.getChildAt(selector).setBackgroundResource(R.drawable.main_button_shape_pressed);
}
}
}
}
).start();
}
}
}
ListViews recycle their children. While drawing itself, the ListView will create a new view for every visible child. When you scroll, it will then re-use the last view that became non-visible (scrolled off the screen) as the next view in the list. That is why it's a different view index in landscape and that is why it would probably be a different view index on a device with a different screen size.
The solution should be to reset the view background in the Adapter's getView() method.
Additionally, touching views on anything other than the UI (main) thread is a bad practice. Check the selected item index in the getView() method and set the background right there. You'll also need to handle the case where the selected index changes (unless it never changes after this activity is created) by iterating over visible views in the listview and setting their backgrounds to the appropriate values.
// Must be final to use inside the ArrayAdapter
final int selector = extras == null ? -1 : extras.getInt("selector");
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
this,
R.array.sounds_array,
android.R.layout.simple_list_item_1) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View newView = super.getView(position, convertView, parent);
// set the background according to whether this is the selected item
if (position == selector) {
// this is the selected item
newView.setBackgroundResource(R.drawable.main_button_shape_pressed);
} else {
// default background for simple_list_item_1 is nothing
newView.setBackground(null);
}
return newView;
}
};

Android listview toggle image by click, changes more than one image

I have a listview and on click I try to change an arrow image inside my listview adapter row.
This works fine, but I have the problem, that not only a single image changes. A few rows above and below the arrow images also change.
It changes the images in every 6th row.
the code for my onClick event is this:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent,View view, int position, long id) {
if (row != null)
{
ImageView PfeilImage = (ImageView) row.findViewById(R.id.imageView1);
PfeilImage.setImageResource(R.drawable.pfeil);
}
ImageView PfeilImage2 = (ImageView) view.findViewById(R.id.imageView1);
PfeilImage2.setImageResource(R.drawable.pfeil_aktiv);
row = view;
getInfoById(position);
}
});
It would be nice if someone could help me with that problem.
thanks in advance
Frank
That's actually normal for how the ListView is setup since it is designed to not re-inflate Views, but instead re-use them; which is why you can't just change the image, you need to change the data it's pointing to.
The solution to this, inside your Adapter's getView() method, is to check the data and set the background image based on that.
You may want to create a new Class to hold your current data and the new image to use holder. ie.
Class ListViewItem
-int imageToUse
-Object whateverDataYouWereOriginallyUsing
and then set the image for that view based on ListViewItem.get(position).imageToUse
Now, when you're actually changing the data based on a user click, you'll need to call notifyDataSetChanged() on the adapter so that it will re-evaluate the UI based on the new DataSet and your getView() method
got it, many thanks.
in my Adapter Class I made a new int variable "myClickedPosition".
In my click event I set this variable and after this I set notifyDataSetInvalid to redraw the listview:
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> theAdapter,View view, int position, long id) {
LazyAdapter mAdapter = (LazyAdapter) theAdapter.getAdapter();
mAdapter.myClickedPosition=position;
mAdapter.notifyDataSetInvalidated();
getInfoById(position);
}
});
and in my getView function I check the clicked position:
if(myClickedPosition == position)
{
PfeilIcon.setImageResource(R.drawable.pfeil_aktiv);
} else {
PfeilIcon.setImageResource(R.drawable.pfeil);
}
Now all is working fine.

Categories

Resources