What is the difference between onBackPressed and onCancel in DialogFragment? - java

When trying to use the back button of a dialog fragment
I'm curious as to the difference between using onBackPressed() (or onBackPressedCallBack) and onCancel().
I tried to define the data forwarding event of the back key using onBackPressedCallback() and OnBackPressedDispatcher() in the dialog fragment, but it didn't work.
In the end, I passed the data using onCancel().
Why doesn't the back key with onBackPressed() work?
UPDATED
public class WritingCommentDialogFragment extends DialogFragment {
OnBackPressedCallback callback;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return view;
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
Toast.makeText(getContext(), "TEST", Toast.LENGTH_SHORT).show();
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
}

onBackPressed() of the dialog itself intercepts the back button press before the host Activity ever gets a shot at it. The default behavior is to call cancel() on the dialog and not pass it on to the Activity. That's why adding your callback to the Activity isn't doing anything. If you want to specifically handle the back button press, you would need to subclass Dialog to override it and use that class as the Dialog you create in onCreateDialog(). Something like this:
public class MyDialogFragment extends DialogFragment {
#NotNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
Dialog dialog = new Dialog(requireContext(), getTheme()) {
#Override
public void onBackPressed() {
MyDialogFragment.this.onBackPressed();
// And maybe you also want to call cancel() here.
}
};
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
private void onBackPressed() {
// your code here
}
}
A dialog is canceled not only when back is pressed, but also if the user taps outside the dialog or presses the cancel button (if you added one to the dialog), or if you manually call cancel() on it or its host DialogFragment. So performing your action in onCancel() covers more events than just the back button being pressed.
A third possible event you can hook onto (with an OnDismissListener) is the dialog being dismissed, which is any time it is closed, including when it is canceled or when the screen rotates.

Related

Change background using shared preference

I have an application that allows my users to customize the background of my application using buttons. My app works like this: First it will lead them to my main activity, where there is a button that they can press to customize the background. When they pressed that button, it will lead them to a dialog fragment that will give users an option to choose which background image they want. I'm able to change my background, however, the shared preference is not functioning correctly. When I close my app and open it, it changes back to my default background, but when I press the dialog fragment button, it then updates the background to whatever they chose.
So basically, the background only updates when I open the button that offers the background images.
I'm not sure if I explained it well so here is a gif of my
problem
The background only updates when I press the terrain button, does anyone have an idea to fix this? I'm still very new to android and java so I'm not sure if I'm just missing something...
PopupTheme.java
public class PopupTheme extends DialogFragment implements View.OnClickListener {
private ImageButton btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn10;
private static final String BG_NAME = "bgName";
private static final String BG_KEY = "bg";
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.activity_popup_theme, container, false);
btn1 = view.findViewById(R.id.btn1);
btn2 = view.findViewById(R.id.btn2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
if (getBackground() != R.drawable.bgscreen1 ){
MainActivity.mainLayout.setBackgroundResource(getBackground());
}
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
MainActivity.mainLayout.setBackgroundResource(R.drawable.bgscreen1);
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
storeBackground(R.drawable.bgscreen1);
break;
case R.id.btn2:
MainActivity.mainLayout.setBackgroundResource(R.drawable.bgscreen2);
Toast.makeText(getContext(), "Clicked", Toast.LENGTH_SHORT).show();
storeBackground(R.drawable.bgscreen2);
break;
}
}
public void storeBackground(int background) {
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(BG_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit(); //accessing the shared pref
editor.putInt(BG_KEY, background);
editor.apply();
}
// getting the background
public int getBackground() {
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(BG_NAME, Context.MODE_PRIVATE);
int selectedBG = sharedPreferences.getInt(BG_KEY, R.drawable.bgscreen1);
return selectedBG;
}
}
Main Activity.java
public class MainActivity extends AppCompatActivity {
private Button btnWatch, btnReadStory, btnFavorites, btnAbout, btnListen;
private ImageButton btnTheme;
static ConstraintLayout mainLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTheme = findViewById(R.id.btnTheme);
mainLayout = findViewById(R.id.layoutMain);
btnTheme.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupTheme popupTheme = new PopupTheme();
popupTheme.show(getSupportFragmentManager(), "Popup Theme");
}
});
}
}
The problem is that you update background of your MainActivity only if you opened the PopupTheme dialog, So you need to move getBackground and update code from PopupTheme to the onCreate method on MainActivity so the code will executed when the user launch the app
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTheme = findViewById(R.id.btnTheme);
mainLayout = findViewById(R.id.layoutMain);
int background = getBackground();
if (background != R.drawable.bgscreen1 ){
mainLayout.setBackgroundResource(background);
}
// Other code on onCreate
}
// Move getBackground method here from PopupTheme
Note: you can use -1 as default value of background and check if it's -1 that mean the user use the default background

How do I connect a button to a Dialog that will edit a TextView, within a FrameLayout, with a users input?

I don't understand DialogFragment at all. How to create one, how to get the user input out of it, and set it into a TextView.
I would like for the TITLE button, when clicked, to bring up a DialogFragment asking the user to enter the title of their Mood Board. The user enters a title. When they click the PostiveButton "Done", the user's title is set into the top left frame of the mood board, which has a TextView with a hint.
Please! Ask questions, because I don't really understand the dialog setup.
Here is a picture of my main_layout, in my MainActivity. Every element has an "#+id/".
The solution you are looking for is a callback:
Create an interface with a method to use as a callback
Implements the interface on the activity
Create the dialog fragment and in onAttach get the interface
Show the dialog fragment on the activity
On dismiss the dialog fragment pass the text using the instance of the interface
interface Callback {
updateText(String text)
}
class CoolActivity... implements Callback
onCreate {
//find your views
showDialogBtn.setOnClickListener(...
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment prev = getSupportFragmentManager().findFragmentByTag("yourTag");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFragment = ExampleDialogFragment.newInstance();
dialogFragment.show(ft, "yourTag");
)
}
#Override
updateText(String text) {
youtView.setText(text)
}
class CoolDialogFragment extend DialogFragment {
private Callback callback;
#Override
void onAttach(Context context) {
callback = (Callback) context
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.dialog_fragment_example, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//find the views in the dialog fragment
closeBtn.clickListener(...
callback.updateText(edittext.getText().toString())
dismiss()
)
}
}
Here is a gist of a dialog fragment
https://gist.github.com/cutiko/7e307efcf7492ea52ef05cd90f9e3203
The problem is you want to connect a dialog fragment with a another component, and you want to do it straigth forward. This is not considered a good practice because yiu create 2 componentes higly attached, so the best would be to use data persistence and some form of react programming
You can make your mood board title textview static then call it to the alertdialog with edittext to set it text (setText)
like this.
final EditText edittext = new EditText(MainActivity.this);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("Input Title")
.setView(edittext)
.setCancelable(false)
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
YourCustomDialog.your_title_textviewMoodboard.setText(edittext.getText().toString());
}
})
.setNegativeButton("Back", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
AlertDialog alert = builder.create();
alert.show();
in your custom dialog. declare your textview static globally
public static TextView your_title_textviewMoodboard;

DialogFragment OnDismissListener not working

i created a DialogFragment with a layout which contains a listview with some items and wanna do something with the value of the selected item but when i try to set the OnDismissListener it gives me an error.
If someone could help me, here is the code snippet where the error occurs.
When the execution reaches the dialog.getDialog().setOnDismissListener... then it gives the exception
FragmentManager manager = getFragmentManager();
PopupRecentBanderolNrs dialog = new PopupRecentBanderolNrs();
dialog.listitems[0] = GetFileContentsFromInternalStorage();
dialog.show(manager, "dialog");
manager.executePendingTransactions();
dialog.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
... some code ..,
}
});
DialogFragment already implements DialogInterface.OnDismissListener, You can override the onDismiss() method in your PopupRecentBanderolNrs class.
if you want set your Listener, you can set in onCreateDialog method:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = ...;// your dialog
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
return dialog;
}

Closing a view class and opening another view class

I call a view class from my activity. Then the view class calls the same activity. Here is the problem, once the activity comes back up, it won't register any more button pushes.(I'm trying to call another view class. Here is some code:
View Class
public class AnimationView extends View {
Activity myActivity;
//...
public AnimationView(Context context, Activity activity) {
super(context);
//...
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//...
myActivity.setContentView(R.layout.activity_home);
}
}
Home Activity
public class HomeActivity extends AppCompatActivity {
private AnimationView mDrawViewA;
///...
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mDrawViewA = new AnimationView(this,this);
start = (Button) findViewById(R.id.startButton);
//...
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//...
setContentView(mDrawViewA);
//calls more views
//......
});
}
I realize now maybe I should have been calling the view classes in different activities, but I would very much like a get all the view classes working within the same activity.
The problem is you're calling setContentView every time you press the "start" button. This method will overwrite the current layout (if any) with the new value you're setting.
What you can do to get the result you're expecting, which, from what I understand, is to add a new AnimationView to your current layout on every button click, you can try something like this:
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AnimationView animationView = new AnimationView(getApplicationContext());
// I'm using ConstraintLayout as an example, since I don't know exactly what layout you're using
ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
// Set the layout params the way you want
addContentView(animationView, params); // This is where the magic happens
}
});
In short, addContentView is the method you should use when you want to add new views into your activity's root layout.
PS.: It's a terribly bad practice to let the views "know" the activity controlling it. It's always the opposite way around: the activity/fragment knows the view(s) it's controlling.

Using android-color-picker in a fragment?

I am fairly new to android development and want to use the Android-Color_picker "AmbilWarna" inside a fragment. I am getting the error:
The constructor AmbilWarnaDialog(HomeFragment, int, new OnAmbilWarnaListener(){}) is undefined.
Is this because I am using a Fragment instead of a Fragment activity The tutorial I was using uses an Activity.
I am using the following tutorial:
http://wptrafficanalyzer.in/blog/android-color-picker-application-using-ambilwarna-color-picker-library/
public class HomeFragment extends SherlockFragment implements TabListener {
private View homeView;
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
homeView = inflater.inflate(R.layout.homefragment, container, false);
Button sColorBtn = (Button) homeView.findViewById(R.id.button2);
OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(View v) {
colorpicker();
}
};
// Setting click event listener for the button
sColorBtn.setOnClickListener(clickListener);
return sColorBtn;
}
public void colorpicker() {
// initialColor is the initially-selected color to be shown in the rectangle on the left of the arrow.
// for example, 0xff000000 is black, 0xff0000ff is blue. Please be aware of the initial 0xff which is the alpha.
AmbilWarnaDialog dialog = new AmbilWarnaDialog(this, 0xff0000ff, new OnAmbilWarnaListener() {
// Executes, when user click Cancel button
#Override
public void onCancel(AmbilWarnaDialog dialog){
}
// Executes, when user click OK button
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
Toast.makeText(getBaseContext(), "Selected Color : " + color, Toast.LENGTH_LONG).show();
}
});
dialog.show();
}
Use this:
AmbilWarnaDialog dialog = new AmbilWarnaDialog(getActivity().getApplicationContext(), 0xff0000ff, new OnAmbilWarnaListener() {
// Executes, when user click Cancel button
#Override
public void onCancel(AmbilWarnaDialog dialog){
}
// Executes, when user click OK button
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
Toast.makeText(getBaseContext(), "Selected Color : " + color, Toast.LENGTH_LONG).show();
}
});
So you have to use getActivity().getApplicationContext() instead of this. It will return with the Context.
If you want a fragment solution for Color Picker, I have made a fork of android-color-picker where DialogFragment is used and is re-created on configuration change. Here's the link: https://github.com/lomza/android-color-picker

Categories