this is my first question here as a Android beginner. I am also not an native speaker, so please excuse my bad english skills.
I want to implement an Android App for renting machines. To add a new contract, i created an AddVertragActivity.java with a spinner. This spinner should be filled with data from a Room database. The problem is, that i can populate the spinner to view all items, but when I click on any item nothing happens. I discovered in debug mode, that the onItemSelected method is never called. I have read many other post here, but nothing solved my problem. Due to the fact, that no error message is shown, I have no idea what to do next. Every time I select an item in the dropdown list, there is a warning in the logfile:D/OpenGLRenderer: endAllActiveAnimators on 0xe54e7a70 (DropDownListView) with handle 0xbc8d3a30.
So I also do some research and only find a few answers, that didn't help me.
Every time I start the activity there is also an warning about HiddenField. But I decreased the android version to Nougat and this warning was obsolet. So that didn't solved the problem either:W/.viewpager_tes: Accessing hidden field Landroid/widget/AbsListView;->mIsChildViewEnabled:Z (greylist, reflection, allowed)
When you need some extra information, let me know. Thanks in advance for any advise.
Activity
public class AddVertragActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private Spinner spinnerB;
private BaumaschinenViewModel bViewModel;
private List<String> baumaschineList = new ArrayList<String>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_vertrag);
spinnerB = findViewById(R.id.spinnerBaumaschine);
bViewModel = new ViewModelProvider(this).get(BaumaschinenViewModel.class);
bViewModel.getAllBaumaschinen().observe(this, baumaschines -> {
for (int i = 0; i < baumaschines.size(); i++) {
baumaschineList.add(baumaschines.get(i).getMachineName());
System.out.println(baumaschines.get(i).getRowid());
}
});
ArrayAdapter<String> spinnerBaumaschinenAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, baumaschineList);
spinnerBaumaschinenAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerBaumaschinenAdapter.notifyDataSetChanged();
spinnerBaumaschinenAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerB.setAdapter(spinnerBaumaschinenAdapter);
spinnerB.setOnItemSelectedListener(this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent.getItemAtPosition(position).equals("Baumaschine auswählen")) {
} else {
String item = parent.getItemAtPosition(position).toString();
Toast.makeText(parent.getContext(), "Selected: " + item, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
You are missing a call to set the item listener that is the reason it is not been called when you clicked any item.
Do something like below. After setting adapter spinnerB.setAdapter(spinnerBaumaschinenAdapter);
spinnerB.setOnItemSelectedListener(this);
Try to use spinnerB.setOnItemClickListener instead of spinnerB.setOnItemSelectedListener.
Hope this helps. Thank you...
Kindly let me know whether it is working or not. Thank you...
Related
I am trying to make carousel with clickable images, made as a list. I want to make so using SetOnItemCLickListener, but when I try to rebuild the project an error pops up and tells me:
error: cannot find symbol method setOnItemClickListener(<anonymous OnItemClickListener>)
I searched the internet for a solution but I am still stuck.
I have tried so far:
Clean the project (obvious);
Searched for name illegal elements, there are none;
When I tried only with SetOnCLickListener it did not work; it is in red-colored letters and there is no method like this.
public class FinalSadMovies extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_final_sad_movies);
List<CarouselPicker.PickerItem> imageItems = new ArrayList<>();
imageItems.add(new CarouselPicker.DrawableItem(R.drawable.joker));
imageItems.add(new CarouselPicker.DrawableItem(R.drawable.starwars_resized));
imageItems.add(new CarouselPicker.DrawableItem(R.drawable.test));
CarouselPicker.CarouselViewAdapter imageAdapter = new CarouselPicker.CarouselViewAdapter(this, imageItems, 0);
carouselPicker.setAdapter(imageAdapter);
carouselPicker.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("MainActivity", "ListView item clicked.");
}
});
If you're using carouselPicker from GoodieBag then setOnItemClickListener is not supported.
The only thing you can rely on is the addOnPageChangeListener but this requires you to change your app UI and flow (because you need to use a button to confirm the selection).
Another option is to create a custom CarouselViewAdapter class where you can handle the click event on the instantiateItem method.
Please give me a hand with an issue I am having with a ListView and its related data in my android development project.
I have an activity called OrderForm that gets started by an Intent from the activity UserProfile as such:
In UserProfile
Intent intent = new Intent(this, OrderForm.class);
startActivity(intent);
Then in OrderForm there is an EditText and an add button to add String items to an ArrayList, and the UI gets populated accordingly.
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
I realize I can use Room for persistence and even SharedPreferences, but
I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
Thanks in advance.
Here is part of the code from OrderForm
public class OrderForm extends AppCompatActivity {
ArrayList<String> list;
ListView itemList;
ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_form);
itemList = findViewById(R.id.itemList);
itemText = findViewById(R.id.item);
linearLayout = findViewById(R.id.no_items_container);
orderContainer = findViewById(R.id.orderContainer);
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(this,
R.layout.list_item,R.id.rowItem, list)
{
#Override
public View getView(int position,
View convertView,
ViewGroup parent) {
// some custom stuff here
}
}
public void addItem(View view)
{
String item = itemText.getText().toString().trim().toLowerCase();
if(!item.isEmpty() && list.indexOf(item) == -1) {
arrayAdapter.add(item);
}
}
You need to understand how Activity lifecycles work.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
Your issue is that when pressing the back button, your OrderForm Activity is destroyed and effectively your arraylist/list view is destroyed. To avoid this problem, you'll have to store the values somewhere for example SharedPreferences, create a text file holding your strings and store it, or return the arraylist back to the UserProfile class where you'll store/handle them (to do that use startActivityForResult() instead of startActivity())
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
In your onCreate() method, you have this:
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(..., list)...
Unless you persist your data in some way, list is always going to be empty when your activity starts up.
I realize I can use Room for persistence and even SharedPreferences, but I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Exactly what you need to store will help define the best way to store it. For a simple list of strings, probably SharedPreferences is the simplest solution.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
These methods are used to store data when an activity is destroyed and then recreated, which commonly happens when the user rotates the device (but can also happen for various other reasons). When you exit your activity (by pressing back to UserProfile), these methods aren't triggered.
I've been searching for awhile but I can't seem to find a solution to my problem. I'm still pretty new to programming. I'm trying to understand how to change the value of a single variable using a spinner. Ideally the user should select "Male" or "Female" from the spinner and receive different outputs based on their selection.
//Two
float Male=(float) (weight*1.9);
float Female=(float) (weight*1.5)`
you will have to work with listeners
Here is the tutorial from java which will help you to understand them better
https://docs.oracle.com/javase/tutorial/uiswing/events/intro.html
after that you can look into the documentation from android developers studio they also give good examples
https://developer.android.com/guide/topics/ui/controls/spinner.html
You can bind your spinner with on selected listener.
spinnerObj.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override public void onItemSelected(AdapterView<?> adapter, View v,int position, long id)
{
if(position == 0)
//Male
else
//Female
}
#Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }
);
I have a ListView subclass that I allow selections on when the context action bar (CAB) is active. The CAB is set as a callback to the onItemLongClick event:
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate a menu resource providing context menu items
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(context_menu, menu);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return true;
}
This is fine, and the ListView works as expected, with the currently selected item staying highlighted when touched.
When I close the CAB, I want the ListView to return to normal (i.e. Touch mode). The problem is that the last selected item remains highlighted indefinitely, regardless of what methods I try to clear it:
public void onDestroyActionMode(ActionMode mode) {
//Unselect any rows
ListView lv = getListView();
lv.clearChoices(); // Has no effect
lv.setChoiceMode(ListView.CHOICE_MODE_NONE); // Has no effect on the highlighted item
lv.setFocusable(false); // Has no effect
lv.setSelection(0); // Has no effect
mActionMode = null;
}
Any suggestions?
The main reason for the problem is that once the ListView selection mode is switched to CHOICE_MODE_NONE, the framework optimizes out the clear operation as it is no longer supporting 'selections'. I have improved the above workarounds a bit by clearing the selection state manually and then setting the mode in a delayed manner so the framework will have its turn to clear the state before turning the mode to CHOICE_MODE_NONE.
final ListView lv = getListView();
lv.clearChoices();
for (int i = 0; i < lv.getCount(); i++)
lv.setItemChecked(i, false);
lv.post(new Runnable() {
#Override
public void run() {
lv.setChoiceMode(ListView.CHOICE_MODE_NONE);
}
});
I faced the same issue and since requesting layout doesn't solve the problem for me either I implemented a little hack which works for me. Maybe this is the same issue because I'm switching between CHOICE_MODE_SINGLE and CHOICE_MODE_NONE.
When the action mode ends I'm calling this code snippet. clearChoices makes sure that all items are not checked anymore (internally). The iteration over the views makes sure that all currently visible views are reset and not checked anymore.
mListView.clearChoices();
for (int i = 0; i < mListView.getChildCount(); i++) {
((Checkable) mListView.getChildAt(i)).setChecked(false);
}
mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
Looking at the ListView sourcecode, the only way to work around this is to set the ListView to CHOICE_MODE_NONE, then re-assign the ListAdapter (which clears the internal selection list regardless of choice mode)
i.e. in a ListFragment/ListActivity
getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
getListView().setAdapter(getListAdapter())
I was having this issue in API Level 17 and solved it by doing:
listView.clearChoices();
listView.invalidateViews();
For me, it seems the accepted answer is not working for invisible items, and it's no need to call
for (int i = 0; i < lv.getCount(); i++)
lv.setItemChecked(i, false);
instead, just call
lv.requestLayout();
To completely solve my issue, I call
lv.clearChoices();
lv.requestLayout();
in onDestroyActionMode()
and call
lv.setItemChecked(position, false)
in onItemClick() when it's not in ActionMode
However, I did not confirm whether call setItemChecked() will result some performance issues
This has been logged as an AOSP bug, but marked as obsolete for whatever reason.
Normally you would expect this to work:
getListView().clearChoices();
getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
Unfortunately it does not. Deferring setting choice mode to none in the next layout pass would work:
getListView().clearChoices();
getListView().post(new Runnable() {
#Override
public void run() {
getListView().setChoiceMode(ListView.CHOICE_MODE_NONE);
}
});
I had tried all the approaches discussed above but none of them work for me. Finally, I decide to apply the following workaround. The key idea is that,
During multimode, instead of reusing the "cached" view, we will create a completely new view. Not efficient, but at least "partially" solve my problem.
Here is the code of my customized ArrayAdapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Key to solve this problem. When we are in multimode, we will not reusing the cached view.
View rowView = this.multimode ? null : convertView;
if (rowView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.watchlist_row_layout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.textView0 = (TextView) rowView.findViewById(R.id.text_view_0);
viewHolder.textView1 = (TextView) rowView.findViewById(R.id.text_view_1);
viewHolder.textView2 = (TextView) rowView.findViewById(R.id.text_view_2);
rowView.setTag(viewHolder);
}
Also, I feel safer to have the following code in ActionMode.Callback, although I'm not sure how much it helps.
#Override
public void onDestroyActionMode(ActionMode mode) {
MyFragment.this.myArrayAdapter.setMultimode(false);
// http://stackoverflow.com/questions/9754170/listview-selection-remains-persistent-after-exiting-choice-mode
// Using View.post is the key to solve the problem.
final ListView listView = MyFragment.this.getListView();
listView.clearChoices();
for (int i = 0, ei = listView.getChildCount(); i < ei; i++) {
listView.setItemChecked(i, false);
}
listView.post(new Runnable() {
#Override
public void run() {
listView.setChoiceMode(ListView.CHOICE_MODE_NONE);
}
});
actionMode = null;
}
Side Note
Using MultiChoiceModeListener couple with CHOICE_MODE_MULTIPLE_MODAL will make this bug gone. However, for device below API level 11 will not able to use this solution.
I know this has been answered, but above answers still gave me problems with the cached/recycled views that ListView maintains, that didn't update it's state when scrolled back into view.
So, the above solution changes slightly to:
lv.clearChoices();
ArrayList<View> list = new ArrayList<View>();
lv.reclaimViews(list);
for (View view : list) {
((Checkable) view).setChecked(false);
}
lv.setChoiceMode(lv.CHOICE_MODE_NONE);
This is better than using getChildAt(i) because that method jusg gives you the currently visble views and does not account for the internal cached views, that are not visible.
I have found that the only two methods that work here (API 19) are:
Resetting the list adapter, which is undesirable because it goes back to the top of the list;
Setting the choice mode to CHOICE_MODE_NONE in a new Runnable
If the choice mode is changed without using listView.post(new Runnable()), it doesn't work. Can anyone explain to me why this is?
Apologies for not commenting; I have no reputation.
Thanks.
Not sure if this is too late just wanted to share. I created an intent to the same page so that once the clicked data is captured it recreates a fresh page without any clicked persistence.
Is not a bug. That behavior is required to support multiple HID for Android.
So to show the selection state you only need set the choice mode of the listview and a background to support the selected state for the "list item layout", like:
android:background="?android:attr/activatedBackgroundIndicator"
FYI: http://android-developers.blogspot.mx/2008/12/touch-mode.html
I am working with Spinner, cursors and adapters.
I want to setup a click listener for the spinner so that once a user selects an item from the spinner it gets the current selected item and then carrys out some other tasks ( all this extra code is fine, its just 1 problem I am having).... It kind of works, however, once I declare the setOnItemSelectedListener callback, since the cursor has already been populated, the event is fired as soon as the app launches.
I guess I need a way to define the cursor without selecting an initial item so that the event doesnt fire (since an item will not be selected). Or is there another better way to achieve this?
Basically, as it stands, once the app loads the setOnItemSelectedListener function is firing because the cursor is being populated ( i think). Moreover, ignoreing the fact that the event is firing too soon, if I then select the -same- item in the spinner, it doesnt fire the event sincethe item didnt change. SHould I be using a different callback instead of setonitemslectedlistener? Here is the code I have so far.
c = db.getallrecents();
startManagingCursor(c);
busnumspinner = (Spinner) findViewById(R.id.Spinner01);
SimpleCursorAdapter spinneradapter = new SimpleCursorAdapter(this,
R.layout.lvlayout, c, spincol, spinto);
busnumspinner.setAdapter(spinneradapter);
busnumspinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String spinnerString = null;
Cursor cc = (Cursor)(busnumspinner.getSelectedItem());
if (cc != null) {
spinnerString = cc.getString(
cc.getColumnIndex("busnum"));
text = spinnerString;
}
showDialog(DATE_DIALOG_ID);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}
});
This has already been discussed in this question. Look there, though it has a similar answer like the one given by blindstuff.
EDIT:
If the onItemSelectedListener is not firing when you need it, then you probably need a onClickListener in eachtext item of the droplist and get in there the current position of the selected item of the spinner. The problem is that as it is said here spinner don't support this event, but maybe you can get it by doing something similar to the explained in this stackoverflow question. I haven't tried it so I'm not sure it will work.
Use a boolean flag to ignore the first time it gets selected by the system, its not a pretty solution, but i've struggled with this a couple of times, and never found a better solution.
you can add first item of spinner by default value like selectvalues and check its position in onitemselected listener, if it's zero position then dont enter in the loop greater than 0 then enter in the method
see the example
busnumspinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int
position, long id) {
if(position!=0)
{
String spinnerString = null;
Cursor cc = (Cursor)(busnumspinner.getSelectedItem());
if (cc != null) {
spinnerString = cc.getString(
cc.getColumnIndex("busnum"));
text = spinnerString;
}
}
So this is not run the default value
Try this:
Extend your SimpleCursorAdapter, override bindView() and set OnClickListener for the row view.
This will overcome both issues: You do not get the initial call, and you get each selection click (inc. re-selection)
Let me know if you need example code.
EDIT: Code example:
protected class NoteAdapter extends SimpleCursorAdapter {
// Constructor
public NoteAdapter(Context context, Cursor c) {
super(context, R.layout.etb_items_strip_list_item, c, fromNote, toNote);
}
// This is where the actual binding of a cursor to view happens
#Override
public void bindView(View row, Context context, Cursor cursor) {
super.bindView(row, context, cursor);
// Save id
Long id = cursor.getLong(cursor.getColumnIndex("_id"));
row.setTag(id);
// Set callback
row.setOnClickListener(row_OnClick);
}
// Callback: Item Click
OnClickListener row_OnClick = new OnClickListener(){
public void onClick(View v) {
Long id = (Long) v.getTag();
}
};
}