I have a program I am working on in Android studio. I am having an issue when getting the input from a user and setting it to a text box. Here is what im working with.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onetap);
// A BUNCH OF STUFF UP HERE
final TextView username_textBox = (TextView) findViewById(R.id.usernameTextBox);
//check for username
askForUsername();
username_textBox.setText(readFile("username.txt"));
// A BUNCH OF STUFF DOWN HERE
}
Here is the askForUsername() method
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter a username (You may not change this)");
// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_NUMBER_VARIATION_NORMAL);
int maxLength = 16;
input.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
username = input.getText().toString();
saveFile("username.txt",username);
}
}).create();
builder.show();
In this case username is a class-wide variable.
Whenever I run askForUsername i put in my username and the box called username_textBox doesnt display the username entered. I know my readFile and saveFile work because I use them for other things.
What happens here is that askForUserName() is not blocking, so readFile gets executed while the dialog is still opening, much before saveFile gets called.
A simple solution to show it in a TextView would be to make username_textBox a class variable and access it directly from dialog's onClick method:
public void onClick(DialogInterface dialog, int which) {
username = input.getText().toString();
username_textBox.setText(username);
// if you need to save it in a file
saveFile("username.txt",username);
}
So your activity class would look something like this:
public class MainActivity extends AppCompatActivity {
TextView username_textBox;
String username;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onetap);
// A BUNCH OF STUFF UP HERE
username_textBox = (TextView) findViewById(R.id.usernameTextBox);
//check for username
askForUsername();
// A BUNCH OF STUFF DOWN HERE
}
void askForUsername(){
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Enter a username (You may not change this)");
// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_NUMBER_VARIATION_NORMAL);
int maxLength = 16;
input.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
username = input.getText().toString();
username_textBox.setText(username);
saveFile("username.txt",username);
}
}).create();
builder.show();
}
From my experience I think that it's not running in sequence.
The readFile("username.txt") is being called during the dialog is showed.
What I would do is implement a method onPositiveResult with the DialogBuilder that handles the event of pressing "OK".
I can elaborate if needed.
Your Activity must tend a bridge between the Dialog and the Activity, this could be done with an Interface like this
public inteface myDialoglistener {
public void stuff( String param);}
then the askForUsername(Activity myAct) should recieve the Activity or Context as a parameter, that way you have access to the interface. Then you modify your Positive method to this:
#Override
public void onClick(DialogInterface dialog, int which) {
username = input.getText().toString();
saveFile("username.txt",username);
myDialoglistener activity = (myDialogListener)myAct
activity.stuff();
}
Finally on your Activity you must override stuff method
#Override
public void stuff() {
//your settext code here
}
Regards!
Related
I am using a dialog in my app that pops up and interacts with the user. I haven't worked with dialogs before, so i know next to nothing about styling them. This is the code:
public void openDialog() {
#SuppressLint("InflateParams") View view = (LayoutInflater.from(AudioRecorder.this)).inflate(R.layout.audio_name_input, null);
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AudioRecorder.this);
alertBuilder.setView(view);
final EditText userInput = view.findViewById(R.id.userInput);
alertBuilder.setCancelable(true);
alertBuilder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
inputName = String.valueOf(userInput.getText());
if (!inputName.isEmpty()) {
Toast.makeText(AudioRecorder.this, "Next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
filePathMaking();
} else {
inputName = "recorded_audio";
Toast.makeText(AudioRecorder.this, "Input field empty, next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
}
}
});
alertBuilder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
Dialog dialog = alertBuilder.create();
dialog.show();
}
Can we style the "Save" button to display red text?
You can get the Button and then change it's text color. Something along the following lines should work,
public void openDialog() {
#SuppressLint("InflateParams") View view = (LayoutInflater.from(AudioRecorder.this)).inflate(R.layout.audio_name_input, null);
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AudioRecorder.this);
alertBuilder.setView(view);
final EditText userInput = view.findViewById(R.id.userInput);
alertBuilder.setCancelable(true);
alertBuilder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
inputName = String.valueOf(userInput.getText());
if (!inputName.isEmpty()) {
Toast.makeText(AudioRecorder.this, "Next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
filePathMaking();
} else {
inputName = "recorded_audio";
Toast.makeText(AudioRecorder.this, "Input field empty, next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
}
}
});
alertBuilder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
Dialog dialog = alertBuilder.create();
dialog.show();
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setTextColor(Color.parseColor("#FF0B8B42"));
}
You can use AlertDialog as Chrisvin Jem suggested in his answer but I would like to offer another solution:
You can just create a custom dialog class in order to give your dialog a custom layout, control everything in a separate class - I find it cleaner and more organized.
For example, create dialogClass:
public class ProgressDialog extends Dialog {
public ProgressDialog(#NonNull Context context) {
super(context);
setContentView(R.layout.progress_dialog); //this is your layout for the dialog
}
}
And all you need to do is to create dialog instant and call it like this:
ProgressDialog progressDialog = new ProgressDialog(getContext());
progressDialog.show(); // this line shows your dialog
Why I recommend using this and not AlertDialog.Builder :
You can build your layout in a faster way with custom dialog.
No need to write a lot of code just to add views when you can have a custom layout.
It's easier (or so I believe) for you to see myCoolDialog.show(); rather than 50 lines of code or more in a single method.
Do you need to change anything regarding your dialog look and code? good, go to your separate class and change it instead of adding 20 more code lines to your activity.
Chrisvin Jem gave the extact answer to your question however if you want more control over your design you can the this code
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.yourview);
RelativeLayout submit = dialog.findViewById(R.id.submit);
final EditText edittext = dialog.findViewById(R.id.edittext);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
Toast.makeText(context, getString(R.string.thanks), Toast.LENGTH_SHORT).show();
}
});
dialog.show();
I realize this issue has been touched on numerous times but nothing I try is working for me. I still get errors when trying to access SharedPreferences.
From the main Activity (McsHome) I am launch a variety of Dialogs to help the user add a location.
The first Dialog is below, this simply pops up a message stating a location needs to be added (PopupMessage.java):
public class PopupMessage extends DialogFragment {
String message = "";
AddLocation addLocation;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
addLocation = new AddLocation();
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(message)
.setPositiveButton("Add Location", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
addLocation.show(getFragmentManager(), "PopupMsgFragment");
}
})
.setNegativeButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//
};
});
// Create the AlertDialog object and return it
return builder.create();
}
}
This gives the user an option to add a location, when that button is clicked another dialog pops up (AddLocation.java):
public class AddLocation extends DialogFragment {
EditText mcsDomain;
EditText friendlyName;
EditText password;
ProcessLocation addLoc;
String message = "";
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View layout = inflater.inflate(R.layout.add_location_dialog, null); // Pass null as the parent view because its going in the dialog layout
mcsDomain = (EditText) layout.findViewById(R.id.mcsDomain);
friendlyName = (EditText) layout.findViewById(R.id.friendlyName);
password = (EditText) layout.findViewById(R.id.password);
builder.setView(layout)
.setTitle("Add/Update Location")
// Add action buttons
.setPositiveButton("Add/Update", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
// Passes the chosen location parameters to the ProcessLocation class
addLoc.processLocation(mcsDomain.getText().toString(),friendlyName.getText().toString(),password.getText().toString());
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
return builder.create();
}
The AddLocation.java uses an XML layout which includes 3 EditText fields. The values of these are passed on to a third Class, ProcessLocation.java which includes the method processLocation().
public class ProcessLocation {
SharedPreferences domainToName;
SharedPreferences nameToDomain;
public void processLocation(String domain, String name, String password) {
domainToName = getSharedPreferences("domainToName", MODE_PRIVATE);
nameToDomain = getSharedPreferences("nameToDomain", MODE_PRIVATE);
// final Editor domainEdit = domainToName.edit();
// final Editor nameEdit = nameToDomain.edit();
if (nameToDomain.contains(name)) {
System.out.println("Name Doesn't Exist");
}
}
}
I'm getting an error on the MODE_PRIVATE, I believe related to Context. I've been playing around with context for hours with no luck (or understanding). I know I'm popping up a couple of dialogs in a row. If I add "extends Activity" the error goes away but then the app crashes when trying to getSharedPreferences.
From going through the other posts I'm sure it's to do with passing the context from my McsHome.java activity but everything I've tried has failed.
First of all, in AddLocation you declare the member variable addLoc, but you never assign it to anything. If you did get this to compile, it would throw a NullPointerException here:
addLoc.processLocation(mcsDomain.getText().toString(), friendlyName.getText().toString(),
password.getText().toString());
getSharedPreferences() is a method of the Context class. In ProcessLocation.processLocation() you are trying to call it. This method doesn't exist in the ProcessLocation class.
You need to do the following:
1) ProcessLocation needs to have a Context reference, so that it can call getSharedPreferences(). The easiest way to do this is to declare a member variable in ProcessLocation of type Context and have it initialized in the constructor of ProcessLocation. Like this:
public class ProcessLocation {
Context context;
SharedPreferences domainToName;
SharedPreferences nameToDomain;
// Constructor
ProcessLocation(Context context) {
this.context = context;
}
2) You need to create an instance of ProcessLocation. In AddLocation, before using the variable addLoc you will need to initialize it. Like this:
// Create instance of ProcessLocation and pass it the activity (Activity is a Context)
addLoc = new ProcessLocation(getActivity);
3) Use the Context in ProcessLocation.processLocation(), like this:
public void processLocation(String domain, String name, String password) {
domainToName = context.getSharedPreferences("domainToName", Context.MODE_PRIVATE);
nameToDomain = context.getSharedPreferences("nameToDomain", Context.MODE_PRIVATE);
...
}
It is late and I'm tired and I didn't put this through a compiler, so please forgive me if I left out a comma or a semicolon or spelled something wrong. Hopefully you get the drift. Good luck!
In my app I am using AlertDialog with EditText. I want to move this code to method because it called few times. I try to implement it by this way:
private EditText showEditAlert(DialogInterface.OnClickListener listener) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(R.string.waypoint);
alert.setMessage(R.string.waypoint_alert_text);
EditText editText = new EditText(this);
alert.setView(editText);
alert.setPositiveButton(android.R.string.ok, listener);
alert.setNegativeButton(android.R.string.cancel, null);
alert.show();
return editText;
}
And then I want to use it:
final EditText editText = showEditAlert(new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Here is I am working with editText
// and here is I get error "The local variable editText may not have been initialized"
}
});
But I get "The local variable editText may not have been initialized" error. As I understand compiler think that the onClick() method will called before showEditAlert() returns value.
How to implement this correctly? Or may be I can just suppress this error?
Looks like the IDE's warning is precisely for the reason you suppose. I guess you could circumvent this by defining a custom interface for the listener (and it would probably be more clear to use, to boot). Something like:
interface EditAlertOkListener
{
void onEditAlertOk(EditText editText);
}
private void showEditAlert(final EditAlertOkListener listener)
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
...
final EditText editText = new EditText(this);
alert.setView(editText);
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
if (listener != null)
listener.onEditAlertOk(editText);
}
});
alert.setNegativeButton(android.R.string.cancel, null);
alert.show();
}
And then just call it with:
showEditAlert(new EditAlertOkListener() {
#Override
public void onEditAlertOk(EditText editText) {
// Use editText here.
}
});
PS. You can also have the method return the EditText, if needed, I just removed it to make this example clearer. Or also, if you just need the EditText contents, have the interface pass a CharSequence or String instead of the EditText itself. This is just a template. :)
Because the editText variable may not be initialized. The IDE could not check it when it is creating.
The solution here is use the keyword: "this"
final EditText editText = showEditAlert(new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
this.getText();// this mean editText, not its parent, if you want to use parent, you must have ParentClass.this
}
});
I'm designing function using AlertDialog to act like a InputBox in VB6. However using the code below, AlertDialog won't return values.
Seems that the function returns before the user makes the input.
public String InputBox(Context srcpage, String Msg, String Title, String InputDataType_TXT_or_NUM)
{
ResetReturnText();
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(srcpage);
dlgAlert.setMessage(Msg);
dlgAlert.setTitle(Title);
// Set an EditText view to get user input
final EditText inputTxt = new EditText(srcpage);
//Set the input type of the EditText
//-------------------------------------------------------
if(InputDataType_TXT_or_NUM=="TXT")
inputTxt.setInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
else if(InputDataType_TXT_or_NUM=="NUM")
inputTxt.setInputType(InputType.TYPE_CLASS_NUMBER);
else
return "Invalid Data Type";
//-------------------------------------------------------
dlgAlert.setView(inputTxt);
dlgAlert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
ReturnText = inputTxt.getText().toString();
}
});
dlgAlert.setNegativeButton("Cancel",null);
dlgAlert.create().show();
return ReturnText;
}
I Want these code to return values with function calls like:
String NewProvince="";
NewProvince = InputBox(this, "Province:", "Add/Edit Province", "TXT");
Log.w("Input:",NewProvince);
Can I ask you guys to help me with fixing this problem?
Thanks!
You have to use a different approach, based on "callback".
So your function has simply to return void and do the stuff inside the onClick listener.
private void buildDialog() {
// build your dialog with everything
dialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// do what you want with the value
doSomethingWithValue(value);
}
});
}
protected void doSomethingWithValue(String value) {
Log.i("MyTAG", value);
}
I am developing an android application. Now i have created one function which create custom dialog box and i want this dialog box to display on every activity. So i need to call this function at every activity. But as the syntax of custom dialog (e.g. Dialog d = new Dialog(home.this)).home is the name of the activity where i have created the function so i am not ale to use this function in any other activity. And i haven't use android that much. So give me good example to solve my problem. Here is my code
here is sample code code of using AlertDialog in all activity.
crate one class file like as allmethod.java
and add this code in that class
public static void showAlert(Activity act,String msg)
{
AlertDialog.Builder alert = new AlertDialog.Builder(act);
alert.setMessage(msg).setPositiveButton("OK", new OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which)
{
}
}).show();
}
and you can use from any class like as
allmethod.showAlert(Activity,"Message");
In your case..
public void SearchDialog(Context ctx){
final Dialog dialog = new Dialog(ctx);
dialog.setContentView(R.layout.dialogsearch);
dialog.setTitle(" Enter The Text to Search");
dialog.setCancelable(true);
final EditText Text = (EditText) dialog.findViewById(R.id.EdText);
Button buttonOK = (Button) dialog.findViewById(R.id.btnOK);
buttonOK.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String SearchText = Text.getText().toString();
prefsPrivate =getSharedPreferences(Login.PREFS_PRIVATE,Context.MODE_PRIVATE);
Editor prefsPrivateEdit=prefsPrivate.edit();
prefsPrivateEdit.putString("Text",SearchText);
prefsPrivateEdit.commit();
Intent i = new Intent(ctx,SearchTask.class);
startActivity(i);
dialog.cancel();
}
});
Button buttonCancel = (Button) dialog.findViewById(R.id.btnCancel);
buttonCancel.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dialog.cancel();
}
});
dialog.show();
}
Just add a Context parameter to your SearchDialog() constructor.
Make it like this:
public SearchDialog(Context context){
//....
}
You could either define your own Interface and implement for every class, or make the main Activity method static (as long as it wont need to access anything in dynamic objects that aren't method arguments).
final class Uutil {
public void static func() {
}
}
then do it in your classes:
class A {
public void f() {
Uutil.func();
}
}