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 } }
);
Related
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...
I have a survey app which is implemented using a viewpager and an arraylist of fragments. The fragments have different view types, some have radio buttons, some input boxes. I want the save the entered data to a shared variable in the parent activity when the user navigates from one fragment to another. When the user reaches the last fragment i want to display the summary of the data. i was thinking of saving the data when the user navigates from one fragment to the next. Also not sure if it is the best way to go about it.
List<Question> questions = new SurveyServiceImpl(getApplicationContext()).getSurveyQuestions(1);
ArrayList<Fragment> questionFragments = new ArrayList<>();
questionFragments.add(HomeFragment.newInstance("", ""));
for (int i = 0; i < questions.size(); i++) {
switch (questions.get(i).getQuestionType()) {
case SELECT:
if (questions.get(i).getMaximumOptionsRequired() == 1)
questionFragments.add(QuestionTypeSelect.newInstance("", questions.get(i)));
else
questionFragments.add(QuestionTypeCheckBox.newInstance("", questions.get(i)));
break;
case INPUT:
questionFragments.add(QuestionTypeInput.newInstance("", questions.get(i)));
break;
default:
}
}
questionFragments.add(EndFragment.newInstance("", ""));
final ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), questionFragments));
Use OnPageChangeListener for: all scrolls; page centered; page scroll changes (start drag, finish center animation)
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
#Override public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
//User started moving current page
}});
Off the top of my head:
Save the data as soon as it is changed in each fragment :
For EditTexts, use TextWatcher : (example) to save the text when it changes in afterTextChanged().
For RadioButtons, use radioButton.setOnClickListener(/**Save data in onClick*/), or radioGroup.setOnCheckedChangeListener if you're using a RadioGroup (example).
Might not be the most efficient solution, but works :) .
Hmm. Well unless you are doing some sort of save checkmarks along the wizard flow that you want to represent that all data for that page was saved, I would not go that route personally. You can easily just recognize pageChanged listener
vpMain.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Generated method stub
}
#Override
public void onPageSelected(int position) {
setCurrentPage(position);
PAGE_TO_RETURN_TO = position;
vpMain.setCurrentItem(PAGE_TO_RETURN_TO);
validate data and allow to scroll or save
}
#Override
public void onPageScrollStateChanged(int state) {
//Generated Method Stub
}
});
but I would prefer to see onPause() of the parent activity handle saving the data personally. But it really depends on your need for the app.
I have three Relativelayout views set up in my XML one after eachother, in my onCreate method I have initialised all three views and setEnabled() to false. Then I have set up a Spinner and I want to enable each view when each respective button is clicked. Is there a way to do this? So far I have (on my Spinner):
public void onItemSelected(AdapterView<?> parent, View arg1,
int position, long arg3) {
// TODO Auto-generated method stub
if (parent.getItemAtPosition(position).equals("Quantity")) {
calSelectInt = 1;
calSeek.setEnabled(true);
calWeight.setEnabled(false);
calFlour.setEnabled(false);
} else if (parent.getItemAtPosition(position).equals("Dough Weight")) {
calSelectInt = 2;
calSeek.setEnabled(false);
calWeight.setEnabled(true);
calFlour.setEnabled(false);
} else if (parent.getItemAtPosition(position).equals("Flour Weight")) {
calSelectInt = 3;
calSeek.setEnabled(false);
calWeight.setEnabled(false);
calFlour.setEnabled(true);
}
}
The cal___ represents each view. The calSelectInt is an attempt to set an Integer for each and call in another method when each Integer is read.
As a result when run, all three views are viewed, any ideas? Why isn't setEnabled working? Or is my code poorly thought out. Thanks
Turns out I had to setVisibility(View.GONE) and (View.VISIBLE) instead of setEnabled(boolean). Strange, that method didn't seem to work for me in the past with other things but hey ho.
I have been unable to find a tutorial helping with multi-selects using cursors. As of right now my logic is working the way I want but the check boxes will not update properly. What am I overlooking?
return new AlertDialog.Builder(this).setTitle("Items")
.setMultiChoiceItems(cur, CHECK, EDATE, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int position, boolean checked)
{
DBM.open();
AlertDialog AD = (AlertDialog) dialog;
ListView list = AD.getListView();
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
itemCur = (Cursor) list.getItemAtPosition(position);
if (checked)
{
//update query
DBM.setChecked(checkCur.getInt(checkCur.getColumnIndex(ID)), itemId, userId, 1);
list.setItemChecked(1, true);
} else
{
DBM.setChecked(checkCur.getInt(checkCur.getColumnIndex(ID)), itemId, userId, 0);
list.setItemChecked(1, false);
}
DBM.close();
}
}).setPositiveButton("OK", new DialogButtonClickHandler()).create();
Dialogs on android can't be modified. If you look at the source code you will see that dialogbuilder delegates all the presentation work to some components and you don't have access to them after creation. Thus changing the state of the components you use for building the dialog won't update the dialog components afterwards.
You can see this mechanism here and here : you don't have access to the access controller after onCreate has been called on the alert controller.
The best if you want to achieve this is to rebuild a new activity and give it a dialog theme.
You can just use the setCursor() method for AlertDialog. Its pretty simple so you probably wouldn't need a tutorial.
A relevant SO questions is here and the docs for it are here
So after digging into the issue a bit and going through a couple different iterations I finally found a solution that I am fairly happy with. With school and work pushing hard I have had little time outside to work on extra projects and I have been sitting with this solution for while now but unable to get it posted.
The final piece to my puzzle was finding the changeCursor function, this fixed the issue of the old data that no longer matched the DB to load. My current hurdle is the time it takes to check a box, there is an obvious lag from clicked to updated. I have found that mutliple records update when one is clicked. I have not been able to find a valid reason for these extra updates.
Below is the code I currently have implemented to have the multi-select working. This just the dialog code, for a working demo I will be posting a project on GitHub for a working prototype of it all in action. (Now made public, Multiselect Dialog)
I am a fairly new Android developer, majority of my Android knowledge has been self taught and learned through the knowledge of online resources. I was working on a school project and wanted to implement a multiselect in a dialog that would update the main activity with the selected choices. Please lend any advice you can on how to improve this.
Pros:
- Populates check boxes properly on load.
- Updates database when check is clicked.
- Keeps display updated after data change.
Cons:
- Must click check box to update value.
- Unable to undo changes made while in dialog. The values save onClick, I have not been able to think of a way to temporarily store the new values until confirmed by the user.
- A single click updates multiple records, also sometimes when choices scroll off the screen values update
#Override
protected Dialog onCreateDialog(int id)
{
switch (id) {
case 0:
LayoutInflater factory = LayoutInflater.from(this);
// Setup of the view for the dialog
final View bindListDialog = factory.inflate(R.layout.multi_list_layout, null);
multiListView = (ListView) bindListDialog.findViewById(R.id.multiList);
// Because I do not know how to properly handle an undo in this situation
// I make the dialog only close if the button is pressed and confirms the changes
return new AlertDialog.Builder(MultiSelectDemoActivity.this).setTitle(R.string.multiSelectTitle)
.setCancelable(false).setView(bindListDialog)
.setPositiveButton(R.string.btnClose, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
updateItemList(); // In my implementation there is a list view
// that shows what has been selected.
}
}).create();
default:
return null;
}
}
private static final boolean ONCREATE = true;
private static final boolean ONUPDATE = false;
private void setupMultiList(Boolean newList)
{
demoDBM.open();
multiCur = demoDBM.getList(userId); // Gets all items tied to the user.
startManagingCursor(multiCur);
// Uses the cursor to populate a List item with an invisible ID column,
// a name column, and the checkbox
demoDBM.close();
if (newList)
{
// Creates a new adapter to populate the list view on the dialog
multiAdapter = new SimpleCursorAdapter(this, R.layout.check_list_item, multiCur, new String[] { DemoDBM.ID,
DemoDBM.NAME, DemoDBM.SEL }, new int[] { R.id.itemId, R.id.itemName, R.id.itemCheck });
multiAdapter.setViewBinder(new MyViewBinder());
multiListView.setAdapter(multiAdapter);
} else
{
// updates the previously made adapter with the new cursor, without changing position
multiAdapter.changeCursor(multiCur);
}
}
#Override
protected void onPrepareDialog(final int id, final Dialog dialog, Bundle args)
{
setupMultiList(ONCREATE);
}
public class MyViewBinder implements ViewBinder
{
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex)
{
int checkId = cursor.getColumnIndex(DemoDBM.SEL);
if (columnIndex == checkId)
{
CheckBox cb = (CheckBox) view;
// Sets checkbox to the value in the cursor
boolean bChecked = (cursor.getInt(checkId) != 0);
cb.setChecked(bChecked); // Switches the visual checkbox.
cb.setOnCheckedChangeListener(new MyOnCheckedChangeListener());
return true;
}
return false;
}
}
public class MyOnCheckedChangeListener implements OnCheckedChangeListener
{
#Override
public void onCheckedChanged(CompoundButton checkBox, boolean newVal)
{
View item = (View) checkBox.getParent(); // Gets the plain_list_item(Parent) of the Check Box
// Gets the DB _id value of the row clicked and updates the Database appropriately.
int itemId = Integer.valueOf(((TextView) item.findViewById(R.id.itemId)).getText().toString());
demoDBM.open();
demoDBM.setChecked(itemId, userId, newVal);
demoDBM.close();
setupMultiList(ONUPDATE);
}
}
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();
}
};
}