Handling external class dialog button in main activity - java

I am trying to create a custom dialog where the button clicks could be handled by the main activity that instantiates it, something like how the AlertDialog.Builder assigns the listeners via its setPositiveButton() and setNegativeButton() methods.
This is what I've done:
// THE MAIN ACTIVITY
public class main_code extends AppCompatActivity {
private commonModule comMod;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
comMod = new commonModule(this);
}
private void showDialog() {
DialogInterface.OnClickListener dialogHandler =
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// process "PROCEED" button
}
};
commonModule.myDialog customDialog = comMod.new myDialog();
customDialog.inputBox(this, "Submit Results",
"Your results will be submitted.", dialogHandler);
}
}
// THE COMMON MODULE CLASS
public class commonModule {
public commonModule(Context context){
this.context = context;
this.activity = (Activity) context;
}
public class myDialog {
public void showDialog(Activity activity, String title, String message,
DialogInterface.OnClickListener dialogHandler) {
final Dialog panel = new Dialog(activity);
panel.requestWindowFeature(Window.FEATURE_NO_TITLE);
panel.setContentView(R.id.customLayout);
panel.setCancelable(false);
TextView panelTitle = (TextView) panel.findViewById(R.id.title);
panelTitle.setTypeface(fontRes(PlayRegular));
panelTitle.setText(title);
TextView msgboxText = (TextView) panel.findViewById(R.id.content);
msgboxText.setTypeface(fontRes(PlayRegular));
msgboxText.setText(message);
Button button1 = (Button) panel.findViewById(R.id.button1);
button1.setTypeface(fontRes(PlayRegular));
button1.setText("ABORT");
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
panel.dismiss();
}
});
Button button2 = (Button) panel.findViewById(R.id.button2);
button2.setTypeface(fontRes(PlayRegular));
button2.setText("PROCEED");
button2.setOnClickListener(dialogHandler);
// error: View.OnClickListener cannot be applied to Dialog.OnClickListener
panel.show();
}
}
}
I tried using View.OnClickListener() as well, but to no success. I would like the dialog builder to be common and generic, and as such, the click listener should be unique for each dialog.
Any suggestion would be really appreciated.
TIA.

Change your dialogHandler to View.OnClickListener instead of DialogInterface.OnClickListener :
private void showDialog() {
View.OnClickListener dialogHandler =
new View.OnClickListener() {
#Override
public void onClick(View v) {
// process "PROCEED" button
}
};
commonModule.myDialog customDialog = comMod.new myDialog();
customDialog.inputBox(this, "Submit Results",
"Your results will be submitted.", dialogHandler);
}
and in the common module:
public void showDialog(Activity activity, String title, String message,
View.OnClickListener dialogHandler) {
...
button2.setOnClickListener(dialogHandler);
panel.show();
}

Related

void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object referenc [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 3 years ago.
I have added one button "btn". I have set onclicklistener, inside the button "btn" I have added another button "btnYes" to show display custom dialog when I add these "btnYes" apps get crash.
When I remove the "btnyes" button app is working.
Can we add onclicklistener for two button inside one button for different work?
Java Code
public class MainActivity extends AppCompatActivity {
private Button btn, btnYes, btnNo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.click);
btnYes = findViewById(R.id.yes);
btnNo = findViewById(R.id.no);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder dialogBox = new AlertDialog.Builder(MainActivity.this);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View myView = inflater.inflate(R.layout.custom_dialogbox, null);
dialogBox.setView(myView);
final AlertDialog mybuilder = dialogBox.create();
mybuilder.setCancelable(false);
btnYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mybuilder.dismiss();
}
});
}
});
}
}
Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.example.customdialog.MainActivity$1.onClick(MainActivity.java:33)
If btnYes and btnNo are on the dialog, then you should initialize these buttons using the AlertDialog's View object.
You have to modify your code like following.
public class MainActivity extends AppCompatActivity {
private Button btn, btnYes, btnNo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.click);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder dialogBox = new AlertDialog.Builder(MainActivity.this);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View myView = inflater.inflate(R.layout.custom_dialogbox, null);
// these button should be initialize here.
btnYes = myView.findViewById(R.id.yes);
btnNo = myView.findViewById(R.id.no);
dialogBox.setView(myView);
final AlertDialog mybuilder = dialogBox.create();
mybuilder.setCancelable(false);
btnYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mybuilder.dismiss();
}
});
}
});
}
}
Hope it helps you.
if you want to display Dialog with choices yes or no, use this
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message)
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// action for yes
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// action for no
}
});
AlertDialog alert = builder.create();
alert.show();
But, if you want to use a custom dialog layout, you should do it like this.
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.YOUR_LAYOUT_HERE);
Button btnyes= dialog.findViewById(R.id.btnyes);
btnyes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.cancel();
}
});

android.view.WindowManager$BadTokenException error while creating dialog box

I am trying to create a Dialog Box from an Non activity Class.
This is my Code
public static void ShowDialogBox(final Context con, final Listener list) {
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(con);
dlgAlert.setMessage("TEXT");
dlgAlert.setTitle("TEXT");
dlgAlert.setPositiveButton("TEXT"),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
dlgAlert.setCancelable(false);
dlgAlert.create().show(); // THIS LINE GIVES ME AN ERROR
}
This is the error which I am getting
android.view.WindowManager$BadTokenException: at
android.view.ViewRootImpl.setView (ViewRootImpl.java:574) at
android.view.WindowManagerGlobal.addView
(WindowManagerGlobal.java:282) at
android.view.WindowManagerImpl.addView (WindowManagerImpl.java:85)
at android.app.Dialog.show (Dialog.java:298) at
PACKAGE NAME AND CLASS
PACKAGE NAME AND CLASS at
PACKAGE NAME AND CLASS
PACKAGE NAME AND CLASS at
PACKAGE NAME AND CLASS.onBackPressed
(Class.java:95) at android.app.Activity.onKeyUp
(Activity.java:2465) at android.view.KeyEvent.dispatch
(KeyEvent.java:2646) at android.app.Activity.dispatchKeyEvent
(Activity.java:2716) at
android.support.v7.internal.view.WindowCallbackWrapper.dispatchKeyEvent
(WindowCallbackWrapper.java:50) at
android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent
(AppCompatDelegateImplBase.java:224) at
com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent
(PhoneWindow.java:2280) at
android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent
(ViewRootImpl.java:4038) at
android.view.ViewRootImpl$ViewPostImeInputStage.onProcess
(ViewRootImpl.java:4000) at
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562)
at android.view.ViewRootImpl$InputStage.onDeliverToNext
(ViewRootImpl.java:3615) at
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581)
at android.view.ViewRootImpl$AsyncInputStage.forward
(ViewRootImpl.java:3698) at
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589)
at android.view.ViewRootImpl$AsyncInputStage.apply
(ViewRootImpl.java:3755) at
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562)
at android.view.ViewRootImpl$InputStage.onDeliverToNext
(ViewRootImpl.java:3615) at
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589)
at android.view.ViewRootImpl$InputStage.deliver
(ViewRootImpl.java:3562) at
android.view.ViewRootImpl$InputStage.onDeliverToNext
(ViewRootImpl.java:3615) at
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581)
at android.view.ViewRootImpl$AsyncInputStage.forward
(ViewRootImpl.java:3731) at
android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent
(ViewRootImpl.java:3892) at
android.view.inputmethod.InputMethodManager$PendingEvent.run
(InputMethodManager.java:2208) at
android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback
(InputMethodManager.java:1849) at
android.view.inputmethod.InputMethodManager.finishedInputEvent
(InputMethodManager.java:1840) at
android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished
(InputMethodManager.java:2185) at
android.view.InputEventSender.dispatchInputEventFinished
(InputEventSender.java:141) at
android.os.MessageQueue.nativePollOnce (Native Method) at
android.os.MessageQueue.next (MessageQueue.java:143) at
android.os.Looper.loop (Looper.java:122) at
android.app.ActivityThread.main (ActivityThread.java:5254) at
java.lang.reflect.Method.invoke (Native Method) at
java.lang.reflect.Method.invoke (Method.java:372) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run
(ZygoteInit.java:902) at com.android.internal.os.ZygoteInit.main
(ZygoteInit.java:697)
Here is the scenario of the user
Activity A -->Opens Activity B-->User presses Back button in Activity B--> On Back button pressed a listener is sent to Activity A --> And then the Dialog Box shown is called.
The issue you are having with the attempt to build your AlertDialog in a separate class is you are passing the AlertDialog the Context of your Activity. You get the error because the AlertDialog requires the WindowManager from the Activity which has the layout--not the Context. This is because Activit extends Context... not the other way around.
In order to make your code work you need to provide the AlertDialog.Builder access to the Activity. So change your code to something like this:
public class TestDialog {
private static final String TAG = TestDialog.class.getSimpleName();
Activity mActivity;
public TestDialog(Activity activity){
mActivity = activity;
}
public void showDialog(){
AlertDialog.Builder b = new AlertDialog.Builder(mActivity);
b.setTitle("Title");
b.setMessage("message");
b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.e(TAG, "showDialog : onClick");
}
});
b.create().show();
}
}
Now you can call the AlertDialog from an Activity lets say in this case MainActivity like this:
TestDialog testDialog = new TestDialog(MainActivity.this);
testDialog.showDialog();
I have not tried this from a Fragment, so I do not know whether this works from a Fragment or whether you will continue to have issues with certain devices. For those reasons, I (and Google!) still strongly suggest that you use the DialogFragment instead, because is has been especially designed for this scenario. Take a look at the Google Docs.:
https://developer.android.com/guide/topics/ui/dialogs
I generally prefer using DialogFragment instead of what you attempted in order to cut down on repetition. Here is an example of a DialogFragment with a custom layout which I have called R.layout.fragment_alert_dialog:
public class AlertDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
private String title;
private String message;
boolean endSuccess = false;
private AlertFinishedDialogListener mListener;
public AlertDialogFragment() {
}
public static AlertDialogFragment newInstance(String title, String message) {
AlertDialogFragment fragment = new AlertDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
#Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
final Context context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_alert_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
// .setTitle(title)
.setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
endSuccess = true;
if(mListener == null) mListener = (AlertFinishedDialogListener) context;
mListener.onAlertFinishedDialog();
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (AlertFinishedDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface AlertFinishedDialogListener {
void onAlertFinishedDialog();
}
}
It incorporates a Listener just in case you need to be notified when the DialogFragment is completed.
First you need to implement the callback:
implements AlertDialogFragment.AlertFinishedDialogListener{
In order to call the AlertDialogFragment you do this from your Activity (also Fragment if necessary).
private void startAlertDialogFragment(String title, String mess){
AlertDialogFragment alert = AlertDialogFragment.newInstance(title, mess);
alert.show(getFragmentManager(), "alertDialogFragment132");
}
#Override
public void onAlertFinishedDialog() {
Log.e(TAG, "onAlertFinishedDialog");
}
Problem
You can show dialogs from activity context only. except TYPE_SYSTEM_ALERT or TYPE_APPLICATION_OVERLAY, which is not recommended if your app does not show emergency notifications to user.
Solution
If you have activity context available then you can show dialog from any class like service, broadcast receiver, or even any class you imagine.
Here is my workaround that can show dialog from any class like i said.
Here is a snippet what i do to show dialog from any class. (Could it
be more simpler!)
import android.app.Dialog;
import android.content.DialogInterface;
public class SampleClass {
void anyMethod() {
Dialog dialog = ApplicationContext.getInstance().showDialog("title", "yourMessage", "Cancel", "Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO: handle button 1 clicked
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO: handle button 2 clicked
}
});
}
}
Now you will implement to make this work.
1. make application class which you will register in android manifest application tag
<application
android:name=".ApplicationContext"
...
>
...
</application>
2. In this application class you will hold live activity object. that will further useful for showing dialog.
ApplicationContext.java
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
public class ApplicationContext extends Application {
private static ApplicationContext mInstance;
private Activity liveActivity;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
#Override
public void onTerminate() {
super.onTerminate();
mInstance = null;
}
public static synchronized ApplicationContext getInstance() {
return mInstance;
}
public Activity getLiveActivity() {
return liveActivity;
}
public void setLiveActivity(Activity liveActivity) {
this.liveActivity = liveActivity;
}
/*
* Show Dialog with Title, Message, Button1, Button2 with Button1 and Button2 Listener
*/
public AlertDialog showDialog(String title, String msg,
String btn1, String btn2,
DialogInterface.OnClickListener listener1,
DialogInterface.OnClickListener listener2) {
if (liveActivity == null) return null;
AlertDialog.Builder builder = new AlertDialog.Builder(liveActivity)
.setTitle(title)
.setMessage(msg)
.setCancelable(false)
.setPositiveButton(btn1, listener1);
if (btn2 != null)
builder.setNegativeButton(btn2, listener2);
AlertDialog alert = builder.create();
alert.show();
return alert;
}
}
Just one more step
3. You will extend all your activity by this base activity class (You can edit your base activity if you already have one.)
import android.support.v7.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {
#Override
protected void onResume() {
super.onResume();
ApplicationContext.getInstance().setLiveActivity(this);
}
#Override
protected void onPause() {
super.onPause();
ApplicationContext.getInstance().setLiveActivity(null);
}
}
Here you go !!!

SetText from a Class to the main XML file

I'm trying to use the .setText within a java class to try to change the value of a TextView on the activity_main XML file, so far i'm getting the NullpointerExeption error and I've read that its due an error when declaring my variable. How can i achieve this? Do i need to declare it first at the mainActivity.java?
On my activity_main.xml i have a button -> it opens a custom listView -> if you press the 2 item on the list view -> it opens a custom alert dialog -> the custom alert dialog it contains 2 buttons -> if you press the second button -> it has to set the text of a TextView that is on activity_main.xml
Any help is appreciated!
MainActivity.java
final TextView KMLabel = (TextView)findViewById(R.id.KMlabel);
activity.main.xml
<TextView
android:id="#+id/KMlabel"
android:layout_alignBottom="#+id/TVKm"
android:layout_toRightOf="#+id/TVKm"
android:textSize="22sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#e6c009"
android:text="KM/H"
android:textStyle="italic"/>
custom.java
public class custom extends BaseAdapter{
Context context;
String Item[];
String SubItem[];
int flags[];
LayoutInflater inflter;
public custom(Context applicationContext, String[] Item, String[] SubItem , int[] flags) {
this.context = context;
this.Item = Item;
this.SubItem = SubItem;
this.flags = flags;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return Item.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.activity_items, null);
//TextView Prueba = (TextView)view.findViewById(R.id.KMlabel);
TextView item = (TextView) view.findViewById(R.id.item);
TextView subitem = (TextView) view.findViewById(R.id.subitem);
ImageView image = (ImageView) view.findViewById(R.id.image);
item.setText(Item[i]);
subitem.setText(SubItem[i]);
image.setImageResource(flags[i]);
return view;
}
viewdialog.java
public class ViewDialog {
public void showDialog(Activity activity, String msg){
final Dialog dialog = new Dialog(activity);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.custom_dialog);
//I'm declaring it like this
final TextView KMLabel = (TextView)activity.findViewById(R.id.KMlabel);
Button dialogButton = (Button) dialog.findViewById(R.id.btn_dialog);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
Button KmPerHr = (Button)dialog.findViewById(R.id.KmPerH);
KmPerHr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//and calling it this way:
KMLabel.setText("MLL/H");
}
});
dialog.show();
}
}
LOGCAT:
FATAL EXCEPTION: main
Process: com.example.dell.getspeed, PID: 3925
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.dell.getspeed.ViewDialog$2.onClick(ViewDialog.java:38)
at android.view.View.performClick(View.java:5721)
at android.widget.TextView.performClick(TextView.java:10936)
at android.view.View$PerformClick.run(View.java:22620)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7406)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
You have to move your code
Button KmPerHr = (Button)dialog.findViewById(R.id.KmPerH);
KmPerHr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//and calling it this way:
KMLabel.setText("MLL/H");
}
});
final TextView KMLabel = (TextView)dialog.findViewById(R.id.KMlabel);
Button dialogButton = (Button) dialog.findViewById(R.id.btn_dialog);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
below the dialog.show() code because code findViewById only work after you pop up dialog.
Create a Global class which extends to application class, then create a texview in Global
Textview t = null;
Then create two static methods to set and get this textview
Public static void setT(TextView p){
t = p;
}
And get it from
Public static TextView getT(){
return t;
}
Set TextView in your activity ,then access this textview from wherever you want until your activity is alive.
Try the code below:
MainActivity class:-------
public class MainActivity extends AppCompatActivity {
private TextView KMlabel;
private Button b;
private ViewDialog vd;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo2);
vd = new ViewDialog();
KMlabel = (TextView) findViewById(R.id.KMlabel);
b = (Button) findViewById(R.id.b);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vd.showDialog(MainActivity.this , KMlabel , "Your Message" , "Your Text");
}
});
}
}
ViewDialog class:------
public class ViewDialog {
public void showDialog(Context context, final TextView v , String msg , final String text) {
createYesNoInfoDialog(context, msg, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
v.setText(text);
}
}).show();
}
private AlertDialog createYesNoInfoDialog(Context finalContext, String message,
DialogInterface.OnClickListener onNoListener, DialogInterface.OnClickListener onYesListener) {
AlertDialog a = new AlertDialog.Builder(finalContext).setTitle(
message)
.setNegativeButton("No", onNoListener)
.setPositiveButton("Yes", onYesListener).create();
return a;
}
}
demo2.xml:-----
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="xcxc"
android:id="#+id/KMlabel"/>
<Button
android:layout_width="match_parent"
android:text="Create Dialog"
android:layout_height="wrap_content"
android:id="#+id/b"/>
</LinearLayout>
R.id.KMlabel is on activity_main.xml so you have to initialize the TextView from MainActivity reference.
final TextView KMLabel = (TextView)activity.findViewById(R.id.KMlabel);
Edit:
You can use callback pattern for this:
ViewDialog:
public class ViewDialog {
// interface for callback
public interface OnSelectListener {
public void onOkSelect();
}
OnSelectListener mOnSelectListener;
public void showDialog(Activity activity, String msg, OnSelectListener mListener){
mOnSelectListener = mListener;
final Dialog dialog = new Dialog(activity);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.custom_dialog);
//I'm declaring it like this
final TextView KMLabel = (TextView)activity.findViewById(R.id.KMlabel);
Button dialogButton = (Button) dialog.findViewById(R.id.btn_dialog);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
Button KmPerHr = (Button)dialog.findViewById(R.id.KmPerH);
KmPerHr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//pass to the implementation if not null
if( mOnSelectListener != null){
mOnSelectListener.onOkSelect();
}
}
});
dialog.show();
}
}
In MainActivity:
// initialize interface
ViewDialog.OnSelectListener mOnSelectListener = new ViewDialog.OnSelectListener(){
public void onOkSelect(){
KMLabel.setText("MLL/H");
}
};
ViewDialog viewDialog = new ViewDialog();
viewDialog.showDialog(this, "Message", mOnSelectListener);
This happens since you are trying to call the TextView within the custom alert dialog. TextView only belongs to the MainActivity. You can call or change that only within the MainActivity class. So please try this below.
MainActivity.class
public class MainActivity extends AppCompatActivity {
private TextView KMlabel;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
KMlabel = (TextView) findViewById(R.id.KMlabel);
}
public void setTextKM(String string){
KMlabel.setText(string);
}
}
ViewDialog class
public class ViewDialog {
public void showDialog(Activity activity, String msg){
final Dialog dialog = new Dialog(activity);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.custom_dialog);
Button dialogButton = (Button) dialog.findViewById(R.id.btn_dialog);
dialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
Button KmPerHr = (Button)dialog.findViewById(R.id.KmPerH);
KmPerHr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MainActivity mainActivity = new MainActivity();
mainActivity.setTextKM("MLL/H");
}
});
dialog.show();
}
}

How to make the button loads the previous page in Android?

I have search a lot in different sites to solve this problem but I can't till now.
I have a simple app with 50 articles, two buttons, previous and next.
All works fine till the last article 50 where the problem is that the user can't choose the previous button 49, only can load from the beginning.
Here is my code: MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextView meditCenterText;
private Button mStartButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
meditCenterText = (TextView) findViewById(R.id.editCenterText);
mStartButton = (Button) findViewById(R.id.startButton);
meditCenterText.setMovementMethod(new ScrollingMovementMethod());
mStartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String TextView = meditCenterText.getText().toString();
startStory(TextView);
}
});
}
private void startStory(String TextView) {
Intent intent = new Intent(this, StoryActivity.class);
intent.putExtra("TextView", TextView);
startActivity(intent);
}
#Override
protected void onResume() {
super.onResume();
meditCenterText.setText("..... ");
}}
StoryActivity.java
public class StoryActivity extends AppCompatActivity {
public static final String TAG = StoryActivity.class.getSimpleName();
private Story mStory = new Story();
private ImageView mImageView;
private TextView mTextView;
private Page mCurrentPage;
private String mName;
private Button mPreviousButton;
private Button mNextButton;
private ScrollView mScrollView;
private Button mStartButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_story2);
//Intent intent = getIntent();
//mName = intent.getStringExtra(getString(R.string.key_name));
if(mName == null){
mName = "";
}
Log.d(TAG, mName);
mImageView = (ImageView)findViewById(R.id.storyImageView);
mTextView = (TextView)findViewById(R.id.storyTextView);
mPreviousButton = (Button)findViewById(R.id.previousButton);
mNextButton = (Button)findViewById(R.id.nextButton);
mTextView.setMovementMethod(new ScrollingMovementMethod());
loadPage(0);
}
private void loadPage(int choice){
mCurrentPage = mStory.getPage(choice);
Drawable drawable = getResources().getDrawable(mCurrentPage.getImageId());
mImageView.setImageDrawable(drawable);
String pageText = mCurrentPage.getText();
//add the name if placeholder included.
//pageText = String.format(pageText,mName);
mTextView.setText(pageText);
if(mCurrentPage.isSingle()){
mPreviousButton.setVisibility(View.VISIBLE);
mNextButton.setText("Start From The Beginning");
mNextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mPreviousButton.setVisibility(View.VISIBLE);
loadPage(0);
}
});
}else{
mPreviousButton.setText(mCurrentPage.getChoices().getText1());
mNextButton.setText(mCurrentPage.getChoices().getText2());
mPreviousButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int previousPage = mCurrentPage.getChoices().getPreviousPage();
loadPage(previousPage);
}
});
mNextButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
int nextPage = mCurrentPage.getChoices().getNextPage();
loadPage(nextPage);
}
});
}}
}
Thanks for help.
It's probably the logic in your Page class. Have a proper look at it, otherwise from the android side everything is alright. One last thing, you should probably use a ViewPager for your app instead of changing the text every time you load a new oage

Android Application crash on dialog Button click

Im trying to make a Dialog close when button is pressed.But Every time i press the button the application crashes.
public class CanvasPaint extends Activity implements OnClickListener {
final Button widthbtn = (Button) findViewById(R.id.widthbtn);
final Button widthpopBtn = (Button) findViewById(R.id.widthpopBtn);
final Context context = this;
final Dialog widthDialog = new Dialog(context);
widthbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
widthpopBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
widthDialog.dismiss();
}
});
widthDialog.show();
}
});
}
That's some inception code. Why are you setting a click listener inside a click listener? It should be more like
widthbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
widthDialog.show();
}
});
widthpopBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
widthDialog.dismiss();
}
});
Your dialog layout is not properly inflated, and therefore, your widthpopBtn will be null. Try inflating the layout like this:
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.your_dialog_layout, null);
Button widthpopBtn = (Button) dialogView.findViewById(R.id.widthpopBtn);

Categories