Capturing user input from an actionbar menu item - java

I am creating a gym app in Android Studio and the first feature I'm trying to implement is to have the user create a workout by clicking on an option in the action bar to add it. Clicking this button brings up an alert dialog with an EditText field to type in the workout name. Later, I will use the input to create a list view with the different workouts added, but for now I am just concerned about capturing the input from this EditText field.
Here is what should happen.. on this screen I click the + button and it brings up an alert dialog box with an EditText field. I want to capture this input in the java main activity file.
Here is the java MainActivity File. I want the input from the EditText field to be stored in the m_Text variable.
public class MainActivity extends AppCompatActivity {
private String m_Text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
//Clicking add workout button in the action bar
//stackoverflow.com/questions/13143006/alert-dialog-from-within-onooptionsitemselected-android
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.action_add_workout:
//final EditText mAddWorkout = (EditText)R.layout.userinput;
//Creating the dialog box for entering the workout name
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter the workout name");
//Create the user input xml file into a java object; capturing the user input from the dialog box
//inflate means "fill"
View view = LayoutInflater.from(this).inflate(R.layout.userinput,null);
final EditText mAddWorkout = (EditText)view.findViewById(R.id.workout_name_input);
builder.setView(R.layout.userinput);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
m_Text = mAddWorkout.getText().toString();
boolean brkpt = true;
}
}); //Second parameter pass in which event listener should trigger when the button is clicked
builder.setNegativeButton("Cancel",null);
builder.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Here is the xml for my actionbar menu item for adding the workout name (main_menu.xml)
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_add_workout"
android:icon="#drawable/ic_add"
android:title="#string/add_workout"
app:showAsAction="always"/>
</menu>
Last, the xml for the EditText (userinput.xml)
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/workout_name_input"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="name..">
</EditText>
When I debug my code, the m_Text variable is always empty if I enter a workout name in the EditText field. I have been stuck on this for days now and I have combed youtube and SO for an answer and haven't found much relating to my issue.
Any insight is greatly appreciated. Thank you.
EDIT: Updated code for MainActivity. I can get control pass to the custom clicker but the input is still not saved. Thanks
public class MainActivity extends AppCompatActivity {
private EditText mAddWorkout;
public class CustomClickListener implements View.OnClickListener {
private final Dialog dialog;
CustomClickListener(Dialog dialog) {
this.dialog = dialog;
}
#Override
public void onClick(View v) {
String editTextValue= mAddWorkout.getText().toString();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
//Clicking add workout button in the action bar
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.action_add_workout:
//final EditText mAddWorkout = (EditText)R.layout.userinput;
//Creating the dialog box for entering the workout name
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter the workout name");
//Create the user input xml file into a java object; capturing the user input from the dialog box
//inflate means "fill"
View view = LayoutInflater.from(this).inflate(R.layout.userinput,null);
mAddWorkout = (EditText)view.findViewById(R.id.workout_name_input);
builder.setView(R.layout.userinput);
builder.setPositiveButton("OK",null);
builder.setNegativeButton("Cancel",null);
AlertDialog alertDialog = builder.create();
alertDialog.show();
Button saveWorkout = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
saveWorkout.setOnClickListener(new CustomClickListener(alertDialog));
builder.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
******FINAL EDIT*******
I've since finished the entire app and thought I would post my alert dialog code in case it helps someone else out. It turns out that this issue with alert dialogs was the only major issue I had, once I got used to android studio and java things really took off. Anyways my gymapp is a nice little app that uses SQLlite to track workouts, exercises, and sets.. I've actually used it in the gym :)
#Override
//Clicking add workout button in the action bar
public boolean onOptionsItemSelected(MenuItem item) {
//Creating the dialog box for entering the workout name
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final EditText input = new EditText(this);
builder.setTitle("Enter the workout name").setView(input).setView(input);
builder.setPositiveButton("OK",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Workout workout = new Workout(input.getText().toString());
long workout_key = myDb.createWorkout(workout);
populateWorkouts();
}
});
builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
return super.onOptionsItemSelected(item);
}
In my case, I use the input to create a workout object and insert it to my database. And obviously you would need a switch statement if you had more than one option in your action bar menu.
Thanks again to the 2 guys that tried to help me.

Here is how you should do this:
Create a customer click listener
private class CustomClickListener implements View.OnClickListener {
private final Dialog dialog;
CustomClickListener(Dialog dialog) {
this.dialog = dialog;
}
#Override
public void onClick(View v) {
String editTextValue= mAddWorkout.getText().toString();
}
}
You should make mAddWorkout value class-level so you can access it easily!
Then :
Set this click listener to your dialog like this
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter the workout name");
//Create the user input xml file into a java object; capturing the user input from the dialog box
//inflate means "fill"
View view = LayoutInflater.from(this).inflate(R.layout.userinput,null);
final EditText mAddWorkout = (EditText)view.findViewById(R.id.workout_name_input);
builder.setView(R.layout.userinput);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
boolean brkpt = true;
}
}); //Second parameter pass in which event listener should trigger when the button is clicked
AlertDialog alertDialog = builder.create();
alertDialog .show();
Button saveWorkout = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
saveWorkout .setOnClickListener(new CustomClickListener(alertDialog));
This is the solution that I use for my own code and works fine; you can do validation inside the onClick method of the click listener and alert the user accordingly!
Good luck!

private android.app.AlertDialog mAlert;
private EditText mAddWorkout;
//Creating the dialog box for entering the workout name
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.userinput,null);
builder.setTitle("Enter the workout name");
mAlert = builder.create();
mAlert.setCancelable(true);
mAlert.setView(view, 10, 10, 10, 10);
if (mAlert != null && !mAlert.isShowing()) {
mAlert.show();
}
mAddWorkout = (EditText) mAlert.findViewById(R.id.workout_name_input);
m_Text = mAddWorkout.getText().toString();
Hope this solves your problem

A bit late, but I had run into the same problem, and found yet another answer. The solution that works for me is...
binding.myEditText.setOnEditorActionListener { _, action, key ->
if (actionId == EditorInfo.IME_ACTION_SEARCH ||
actionId == EditorInfo.IME_ACTION_DONE ||
key == null ||
key.keyCode == KeyEvent.KEYCODE_ENTER) {
// Put your actions here
true
} else {
false
}
}
I have only been writing kotlin for a month or so, so I cannot promise this follows best practice, but maybe someone else can improve this.
This task is hard because we had only one control, so it is harder to trap focus changes. If we had a page full of buttons, we might have a [Reset] and a [Save] button. We have one function that loads all the parameters into the EditTexts (used on entry and Reset); and one function that updates all the parameters with the EditText text (used on Save). Then all is easy. But I was going to get one parameter going before adding th fancy stuff, which is why I fell into this hole.

Related

Cancel/dismiss alertdialog builder from any other method in same class in android?

I have a java class not activity. From any other activity, I called this class and in that class I created alertdialog builder. In that I inflate data from db.
Now In this class, I have other listener and method also. In one of the method, I want to dismiss/cancel this dialog. Like how we do
setResult(RESULT_OK, intent);
finish();
in any activity, same thing I want to do in class.
Code: This method I called from activity.
public void showProvidersDialog(long customCategoryId) {
categoryId = customCategoryId;
LayoutInflater li = LayoutInflater.from(context);
promptsView = li.inflate(R.layout.row_providers_layout, null);
init();
alertDialogBuilder = new android.app.AlertDialog.Builder(context, R.style.dialogBoxStyle);
alertDialogBuilder.setView(promptsView);
alertDialogBuilder.setNegativeButton(context.getString(R.string.cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
isInsurance();
alertDialogBuilder.show();
//solved: dialog = alertDialogBuilder.create();
dialog.show();
}
And I have one more method in same java class, from that method I want to dismiss currentlt opened dialog.
private void sendProviderData(General provider) {
Singleton.getInstance().setProviderId(provider.getId());
Singleton.getInstance().setProviderIcon(provider.getIcon());
Singleton.getInstance().setProviderName(provider.getName());
//solved
dialog.dismiss
}
Explain once again: See, I can cancel dialog inside negative button. But what I want is, in that dialog I inflate row which includes one contact list. I want that when user click on any of the contact (which is let's say clicked on recycler on touch listener) I'm passing some data using singleton and at that same time, I want to dismiss dialog.
Here's dialog code for generic purpose. You can call whenever you need to show the dialog. You can show dialog by calling showDialog() method & dismiss by calling dismissDialog() method.
/*
* call whenever dialog is required in whole app in form of popup
*/
public class MyDialog implements View.OnClickListener {
private Dialog dialog;
private Context context;
private TextView tvTitle;
private TextView tvSubtitle;
private Button bt_ok;
private String strInvalidUserNamePass, strHeader;
/*
* constructor to change the text dynamically.
*/
public MyDialog(Context context, String strHeader, String invalidUserNamePass) {
this.context = context;
this.strInvalidUserNamePass = invalidUserNamePass;
this.strHeader = strHeader;
if (context != null) {
initDialog();
}
}
/*
* set id of all the view components and implement listeners
*/
private void initDialog() {
dialog = new Dialog(context, R.style.FMDialogNormal);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog_validation);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
dialog.show();
tvTitle = (TextView) dialog.findViewById(R.id.tv_title);
tvSubtitle = (TextView) dialog.findViewById(R.id.tv_subtitle);
tvTitle.setText(strHeader);
tvSubtitle.setText(strInvalidUserNamePass);
bt_ok = (Button) dialog.findViewById(R.id.bt_ok);
bt_ok.setOnClickListener(this);
}
/*
* Implement listener according to the views
*/
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bt_ok:
dialog.dismiss();
break;
}
}
public void showDialog(){
if(dialog!=null){
dialog.show();
}
}
public void dismissDialog(){
if(dialog!=null && isVisible()){
dialog.show();
}
}
public boolean isVisible() {
if (dialog != null) {
return dialog.isShowing();
}
return false;
}
}

EditText Focus and Cursor Selection is Inputting to the Wrong Input Field

I have two EditText fields in my android app. When input is invalid in the first field, an alert dialog is triggered and I try to switch focus and the input cursor back to the EditText field (RollId) that was invalid so it can be re-entered.
The focus change and input cursor actually appears to have worked, but when I start entering input again, it all show up in the wrong editText (Location) field.
final EditText RollId = findViewById(R.id.scan_roll_id);
final EditText Location = findViewById(R.id.scan_location);
RollId.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (!hasFocus) {
if (validate.ValidateRollId(String.valueOf(RollId.getText()))) {
// TODO: parse and populate labels
} else {
// Not a valid RollId format
AlertDialog alertDialog = new AlertDialog.Builder(MoveMaterialActivity.this).create();
validate.RollIdAlert("The scanned Roll Id has the incorrect format. Please enter manually.", alertDialog);
TextKeyListener.clear(RollId.getText());
RollId.setSelection(0);
Location.clearFocus();
RollId.requestFocus();
}
}
}
});
I guess I am basically trying to figure out how to block the input from Location EditText field, or switch it to the RollId EditText field. I thought RollId.setSelection(0) would achieve this.
edit: RollIdAlert())
public void RollIdAlert(String message, AlertDialog alert) {
alert.setTitle("RollId Format Invalid");
alert.setMessage(message);
alert.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.show();
}
Modify your validate.RollIdAlert() method to include a 3d parameter: EditText et
In your listener for the closing of the alert dialog, after dismiss();, put these lines:
et.requestFocus();
et.setSelection(0);

How to make checkbox in alert dialog align left?

It is possible to modified the checkbox align left in alert dialog?
this is activity.java file
AlertDialog dialog;
final CharSequence[] items = {" Easy "," Medium "," Hard "," Very Hard "};
// arraylist to keep the selected items
final ArrayList seletedItems=new ArrayList();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select The Difficulty Level");
builder.setMultiChoiceItems(items, null,
new DialogInterface.OnMultiChoiceClickListener() {
// indexSelected contains the index of item (of which checkbox checked)
#Override
public void onClick(DialogInterface dialog, int indexSelected,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
// write your code when user checked the checkbox
seletedItems.add(indexSelected);
} else if (seletedItems.contains(indexSelected)) {
// Else, if the item is already in the array, remove it
// write your code when user Uchecked the checkbox
seletedItems.remove(Integer.valueOf(indexSelected));
}
}
})
// Set the action buttons
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// Your code when user clicked on OK
// You can write the code to save the selected item here
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// Your code when user clicked on Cancel
}
});
dialog = builder.create();//AlertDialog dialog; create like this outside onClick
dialog.show();
}
.........................................................................
http://i.stack.imgur.com/rTpYb.jpg">
but... I want the checkbox displayed at the left side...anyone help me.
You can put custom view in your alertdialog. In that view you can easily align your checkbox where you want. For more read this tutorial. http://www.pcsalt.com/android/create-alertdialog-with-custom-layout/#sthash.yN5edpAX.FKWQjxBj.dpbs
Try this way,hope this will help you to solve your problem.
dialog = builder.create();
dialog.getWindow().setGravity(Gravity.LEFT);
dialog.show();

onButtonClick vs. onMenuItemSelected ----- Not the same result

I have a method deleteDilaog (it displays dialog with yes and no option. when clicked yes it does something, when clicked no it cancel dialog) and it is called either buy taping a button or on selecting a item in a option menu. Problem is, result is not the same? It works fine when selected from menu but when clicking a button it just displays dialog and no matter what i click,nothing happens?
Button:
private void RemoveAll(){
Button button=(Button) findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteDialog();
}
});
}
Menu Item:
#Override
public boolean onMenuItemSelected(int id, MenuItem item) {
mDeleteId=item.getItemId();
switch(item.getItemId()) {
case INSERT_ID:
addItem();
return true;
case DELETE_ALL_ID:
deleteDialog();
break;
}
return super.onMenuItemSelected(id, item);
}
deleteDialog method:
private void deleteDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setMessage
(CONFIRM_DIALOG_STRING).setCancelable(false).setPositiveButton
(POSITIVE, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int
which) {
switch (mDeleteId) {
case DELETE_ALL_ID:
mDbHelper.removeAllLists();
fillData();
break;
case DELETE_ID:
Cursor c = (Cursor)
getListView().getAdapter().getItem(which);
mDbHelper.removeList
(mItemId);
c.requery();
break;
}
}
}).setNegativeButton(NEGATIVE, new OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int
which) {
dialog.cancel();
}
});
AlertDialog alertDialog = dialog.create();
alertDialog.show();
}
A dialog firstly should never be called as you have coded.
Make us of Activity.onCreateDialog to initialise and maintain you dialog lifecycle
Activities provide a facility to manage the creation, saving and restoring of dialogs. Also See onCreateDialog(int), onPrepareDialog(int, Dialog), showDialog(int), and dismissDialog(int).
It looks like the problem is with mDeleteID. It is set in OnMenuItemSelected, but not in button2's onClick listener.
I'm guessing that the switch(mDeleteID) falls through when the button is clicked.
In case of button you're not setting a value to mDeleteId.

onItemContextMenu and button created programatically problem

I would like if anybody could help to solve the problem, that I'm trying to fix in my code. I'm really despearte!
I would like to know if it's possible get from the contextmenu, all the information of the button that I created, and use the setText function later.
Ok, first of all I create a tablerow with some buttons (like a soundboard application)
for (int j = 0 ; index > 0 && j < 2 ; j++) {
final CustomToggleButton tagB = new CustomToggleButton(this);
tagB.setId(index);
...
...
registerForContextMenu(tagB);
tagB.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
....
}
...
}
}
Secondly, I let every button an "edit" option for changing the text in it:
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderTitle("Opciones de la etiqueta");
menu.add(0, v.getId(), 0, "Edit");
}
Finally I use onContextItemSelected for creating an EditText Alert and let the possibility of introduce the new text.
#Override
public boolean onContextItemSelected(final MenuItem item) {
if (item.getTitle() == "Edit") {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
final EditText input = new EditText(this);
alert.setView(input);
alert.setTitle("Nombre del tag");
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String value = input.getText().toString().trim();
Log.v(null, "nombre del tag nuevo: "+value);
Toast.makeText(getApplicationContext(), value,Toast.LENGTH_SHORT).show();
int button_id = item.getItemId(); // BUTTON ID?
//CustomToggleButton tagB = (CustomToggleButton) findViewById(R.id.button_id);//DOESN'T WORK!!
//CustomToggleButton tagB = (CustomToggleButton) findViewById(button_id); // NEITHER DOESN'T WORK!!
}
});
alert.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
alert.show();
return true;
}
else return super.onContextItemSelected(item);
}
The problem is that I can't use its id from R.java, because I have created the button programatically...
Is there any solution for this problem??
You don't need the ID of the button. You need to reference the Button object you created via code.
Edit: Just define the button object with the scope you require. You probably need class scope. You could use an array or list if you would like. Depending on how many buttons you have, that may be the way to go.

Categories