Android/ Java closure onClick problem? - java

Here is basically my code:
private Dialog mDialog;
private BluetoothAdapter mBluetoothAdapter;
...
private void onCreate(Bundle savedInstanceState) {
...
enabltBTButton = getMyButton();
enableBtButton.setOnClickListener(this.enableBT);
...
}
...
public View.OnClickListener enableBT = (new View.OnClickListener() {
public void onClick(View view) {
mDialog.hide();
mBluetoothAdapter.enable();
Toast.makeText(Main.this, "Bluetooth enabled", Toast.LENGTH_LONG).show();
return;
}
});
The problem: when I click the button nothing happens! I am positive that enableBTButton is referring to the correct object, but my guess is that this has something to do with my referencing mDialog and mBluetoothAdapter, both of which are declared outside of the inner onClick function.
What is an alternative solution to this?

In the pasted code you have:
private void onCreate()
but it should be:
protected void onCreate (Bundle savedInstanceState)
If it really is a "private onCreate()" in your code, then it won't get called by the framework because it doesn't override Activity.onCreate(Bundle), which means the onClickListener is not set up for your button either.

I think the problem is that you are calling a function setOnClickEventListener, but you should be calling setOnClickListener. Is setOnClickEventListener a function you wrote?
(By the way, you can test your guess about referencing mDialog and/or mBluetoothAdapter by commenting out those lines. I don't think that's the problem.)

Rather then keep fumbling with what I had, I decided that to use an AlertDialog, which seems to get the job done quite well. Thank you everyone for your solutions.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Bluetooth is not enabled...")
.setCancelable(false)
.setPositiveButton("Enable it!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Toast.makeText(getApplicationContext(), "Bluetooth enabled", Toast.LENGTH_LONG).show();
...
}
})
.setNegativeButton("Leave it!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Toast.makeText(getApplicationContext(), "Bluetooth still disabled", Toast.LENGTH_LONG).show();
}
});
AlertDialog mAlert = builder.create();
mAlert.show();

Related

When making an AlertDialog the variables don't appear defined

I'm having problems with my first app (learning android studio as i go), I'm trying to insert a Alert Dialog whenever the user clicks on the list item to make sure he wants to delete the item. However, I can't get it working, here's the code if you need more just ask for it. Oh I'm portugues btw, so don't get confused by the variables.
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {
private EditText tarefasET;
private Button btn;
private ListView tarefasList;
private ArrayList<String> tarefas;
private ArrayAdapter<String> adapt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tarefasET = findViewById(R.id.todoEditText);
btn = findViewById(R.id.addBtn);
tarefasList = findViewById(R.id.lvTarefas);
tarefas = FileHelper.lerData(this);
adapt = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, tarefas);
tarefasList.setAdapter(adapt);
btn.setOnClickListener(this);
tarefasList.setOnItemClickListener(this);
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.addBtn:
String newTarefa = tarefasET.getText().toString();
adapt.add(newTarefa);
tarefasET.setText("");
FileHelper.escreve(tarefas, this);
Toast.makeText(this, "Tarefa Adicionada", Toast.LENGTH_SHORT).show();
break;
}
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int posicao, long id) {
AlertDialog confirmDialog = new AlertDialog.Builder(this)
.setTitle("Confirmação")
.setMessage("De certeza que pretende eliminar a tarefa?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
tarefas.remove(posicao);
adapt.notifyDataSetChanged();
FileHelper.escreve(tarefas, this);
Toast.makeText(this, "Tarefa Eliminada", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
What can i do? The app is suposed to be a to-do list, and i can already add and delete files. But i wanted to make a confirmation dialog when the user decides to delete the item he has to-do. But the code gives me the folowing error when i try and lauch the app to the emulator.
the error i'm getting
I suppose you are trying to reference your activity class via this variable. Use class name before this keyword to get outer reference:
FileHelper.escreve(tarefas, MainActivity.this);
Why the problem appears?
Because of the variable scope. The same rules apply to this keyword. Imagine it as a default final variable defined for you by the language.
In your particular case, this keyword references the instance of DialogInterface.OnClickListener you created. The same issue will appear in case any of the MainActivity class level variables names will clash with a variable name of method level variable defined in onClick:
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ArrayList<String> tarefas = new ArrayList();
ArrayList<String> outerTarefas = MainActivity.this.tarefas; // not just tarefas or this.tarefas
}
}

edit text in alert dialog

i've this dialog
case DIALOGO_EDIT:
final EditText editText = new EditText(context);
builder.setView(editText);
builder.setPositiveButton("Send", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
}
});
builder.setNegativeButton("Close", null);
break;
But when i rotate the device the dialog dismiss... How can i solve this problem and mantein the dialog during rotation? Or display the edit text at "full screen" like WhatsApp
When the screen is rotated, the activity actually is restarted and killed, so you need to save and be able to restore the data using the lifecycle methods. Have a look here: Saving Persistent State
You may want to have a look to this question here
The best way of avoid this problem is to use DialogFragment.
Create a new class extended to DialogFragment. Override onCreateDialog and return your old Dialog or an AlertDialog.
Them you can show it with DialogFragment.show(fragmentManager, tag).
Here an example with the activity like listener:
public class MyDialogFragment extends DialogFragment {
public interface YesNoListener {
void onYes();
void onNo();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof YesNoListener)) {
throw new ClassCastException(activity.toString() + " must implement YesNoListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dialog_my_title)
.setMessage(R.string.dialog_my_message)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((YesNoListener) getActivity()).onYes();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
((YesNoListener) getActivity()).onNo();
}
})
.create();
}
}
And in the Activity you call:
new MyDialogFragment().show(getSupportFragmentManager(), "tag"); // or getFragmentManager() in API 11+
This kind of questions already asked,and there are also solution for it, these three questions are matched with your problem (and they answered):
Android Best way of avoid Dialogs to dismiss after a device rotation
Android DialogFragment vs Dialog
How can I show a DialogFragment using compatibility package?

Preventing Android dialog from extending activities

How can I prevent my dialogs from extending activities?
When I create it in my main activity it doesn't dismiss itself when I click "Okay", which creates a new activity. The new activity that is created extends from the MainActivity.
I am using shared preferences to determine where to send the user when they open the app. I'm not sure if that could be playing into this situation.
I want to prevent the dialogs from extending the MainActivity. It shouldn't be showing up on the other activities that I create.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SharedPreferences sharedPreferences = getSharedPreferences("version", 0);
int savedVersionCode = sharedPreferences.getInt("VersionCode", 0);
int appVershionCode = 0;
try { appVershionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; }
catch (NameNotFoundException nnfe) { Log.w(TAG, "$ Exception because of appVershionCode : " + nnfe); }
if(savedVersionCode == appVershionCode){
// Returning user
Log.d(TAG, "$$ savedVersionCode == appVershionCode");
// Temporary Navigation
final Builder alertDialogBuilder = new Builder(this);
new AlertDialog.Builder(new ContextThemeWrapper(getBaseContext(), android.R.style.Theme_Dialog));
alertDialogBuilder.setTitle("Temporary Navigation");
alertDialogBuilder.setMessage("Go to the new activity.");
alertDialogBuilder.setPositiveButton("Okay", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent newactivity = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(newactivity);
dialog.cancel();
}
});
alertDialogBuilder.show();
// End
} else {
// First time visitor
Log.d(TAG, "$$ savedVersionCode != appVershionCode");
// Hide graphics meant for returning users
((Button)findViewById(R.id.Button01)).setVisibility(View.INVISIBLE);
SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
sharedPreferencesEditor.putInt("VersionCode", appVershionCode);
sharedPreferencesEditor.commit();
Builder alertDialogBuilder = new Builder(this);
alertDialogBuilder.setTitle("Welcome");
alertDialogBuilder.setMessage("Click Okay to continue.");
alertDialogBuilder.setNeutralButton("Okay", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent leagues = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(leagues);
}
});
alertDialogBuilder.show();
}
}
Try dialog.dismiss() like such:
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d(TAG, "$$ onClick");
Intent newactivity = new Intent(MAINACTIVITY.this,NEWACTIVITY.class);
startActivity(newactivity);
dialog.dismiss();
}
From a little understanding of your code, my suggestion would be keeping a check of when you want dialog to be shown and when you dont. e.g You can use a static boolean flag showDialog, set it true/false in your activity according to the use.
if(savedVersionCode == appVershionCode && showDialog)
if(savedVersionCode == appVershionCode && !showDialog)
Its more over over a programmatic problem with a programmatic solution. This is approach would be just a suggestion. As you are following a singleTon type of structure so you must be sure of methods you want to carry further.
Second approach could be, do not do it this way. The common method you want to implement in your activity is related to SharedPref checking, so why not :
Create a class which extends Activity.
Add your SharedPref related methods in it.
Now you can extend that class to all you activities.
public class commonMethod extends Activity{
public void my_sharedPrefMethod(){
// do some thing with prefs
}
#OverRide
public void onCreate(){
super.onCreate();
// common onCreate code for every activity. Recommend not to change this
// so that you can implement
}
// you can also write other methods onPause(), onDestroy() here too.
{
Now you can extend your classes with this class commonMethod. e.g
public class main extends commonMethod{
#overRide
public void oncreate(){
}
#overRide
public void my_sharedPrefMethod(){
}
public void showMyDialog(){
// this way dialog box would not be shown on every activity but just this one.
}
}

AlertDialog.Builder show(), crash in click handler

My app opens a new view from the main view with:
Intent ElementsIntent = new Intent(this, ElementList.class);
startActivityForResult(ElementsIntent, 0);
which shows a list of elements and when pushing 1 of these elements a view opens up the same way as before with a new Activity. Inside this view I would like to show a AlertDialog in a button click handler, but when I call show() the app crashes.
I am pretty sure it has got somthing to do with the Context not being correct according to where I try and open the dialog, but I have tried making a static context from the main view, I have tried with element.this, which is the class connected to the activity, and I have tried getApplicationContext, and all of these result in an app crash.
I hope someone can explain what I am doing wrong.
Thanks.
Here is the AlertDialog code which crashes:
public void GoBackClickHandler(View v)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ElementItem.this);
builder.setMessage("Skal ændringer i besvarelse gemmes?")
.setCancelable(false)
.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
if(inputIsValue())
{
UpdateELement task = new UpdateELement();
task.applicationContext = ElementItem.this;
task.execute(1);
}
}
})
.setNegativeButton("Nej", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
If I move this code to the OnCreate, then the alert shows just fine and no app crash. It is only if I place it in a ClickHandler it crashes.
I finally found a soloution to this issue.
I had to save the context of the Activity in a variable in the onCreate method and then use this in the ClickHandler AlertDialog call, then everything works.
Hope this will be of help to someone else with this annoying problem.
public class SplashActivity extends AppCompatActivity implements DialogInterface.OnClickListener {
//Object to hold the listener instance
DialogInterface.OnClickListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
//Assign this to listener.
listener = this;
handler.postDelayed(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(SplashActivity.this);
builder.setTitle("Alert");
builder.setMessage("Alert Message...!");
//Here pass the listener object.
builder.setPositiveButton("OK", SplashActivity.this.listener);
builder.show();
}
});
}
#Override
public void onClick(DialogInterface dialog, int which) {
SplashActivity.this.finish();
}
}

How to raise a Toast on top of a AlertDialog?

I am validating an AlertDialog, and I would like to raise a Toast on top of the AlertDialog display.
I have this code, but the Toast is displayed on the activity
new AlertDialog.Builder(this).setTitle(R.string.contact_groups_add)
.setView(addView).setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
if (wrapper.getTitle().length()>0)
{
processAdd(wrapper);
} else {
Toast.makeText(getApplicationContext(), "Name is required", Toast.LENGTH_SHORT).show();
}
}
}).setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// ignore, just dismiss
}
}).show();
Instead of using AdvertDialog.Builder, you can create a custom dialog which will behave like a dialog, but is in fact a normal activity. Your toasts should be drawn normally on top of this.
Had this problem myself as well, when I wanted to show a validation message within a dialog.
The answer that seanhodges gave is probably the cleaner and better way. But a seperate activity wasnt practical for me, so i came up with this solution.
Anyway, you can use the AlerDialog.Builder, and show a toast.
If you override the OnClickListener of the button the you want to trigger the toast, you can show a toast on top of a dialog.
An example;
public void showToastOnDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Dialog title");
builder.setMessage("Dialog message");
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing, you will be overriding this anyway
}
});
builder.setNegativeButton(android.R.string.cancel,
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// You can implement code here, because you wont be
// overriding this
}
});
final AlertDialog dialog = builder.create();
// Make sure you show the dialog first before overriding the
// OnClickListener
dialog.show();
// Notice that I`m not using DialogInterface.OnClicklistener but the
// View.OnClickListener
dialog.getButton(Dialog.BUTTON_POSITIVE).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast toast = Toast.makeText(context,
"I`m a toast on top of a dialog.",
Toast.LENGTH_LONG);
toast.show();
// Because you are overriding the OnClicklistener, the
// dialog will not auto dismiss
// after clicking
dialog.dismiss();
}
});
}
Try this:
AlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);

Categories