Catch dialog close event from caller class - android

I have a custom dialog.
How can I catch dialog close event from class which call dialog?
class DialogShow {
companion object {
fun showDialog() {
//some logic
val customDialog = CustomDialog(account, context)
customDialog.onDismissListener = {
// here I need to return close event
}
customDialog.show(activity,"rawer")
}
}
}
calss CallDialog{
DialogShow.showDialog()
//here I need to catch dialog dismiss
}
I need to catch this event from kotlin and Java classes.

Create a callback parameter in your function, and call it in the onDismissListener:
class DialogShow {
companion object {
fun showDialog(context: Context, onDismiss: ()->Unit) {
//some logic
val customDialog = CustomDialog(account, context)
customDialog.onDismissListener = {
onDismiss()
}
customDialog.show(context, "rawer")
}
}
}
fun foo() {
DialogShow.showDialog(context) {
// code that is run after dialog is closed
}
}

Related

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property dialog has not been initialized

I just started learning Kotlin. I am using a custom ProgressDialog. Everytime I press back from the MainActivity, the app crashes with the following error:
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property dialog has not been initialized
at com.devApps.blog.CustomProgressDialog.getDialog(CustomProgressDialog.kt:17)
Here is my CustomProgressDialog :
private val progressDialognew = CustomProgressDialog()
lateinit var dialog: CustomDialog
fun show(context: Context): Dialog {
return show(context, null)
}
fun show(context: Context, title: CharSequence?): Dialog {
val inflater = (context as Activity).layoutInflater
val view = inflater.inflate(R.layout.progress_dialog_view, null)
if (title != null) {
view.cp_title.text = title
}
dialog = CustomDialog(context)
dialog.setContentView(view)
dialog.show()
return dialog
}
And this is my MainActivity code :
private val progressDialognew = CustomProgressDialog()
progressDialognew.show(this, "Optimizing Image...")
{
my tasks here
}
override fun onDestroy() {
super.onDestroy()
progressDialognew.dialog.dismiss()
}
UPDATE : I did as suggested now I am getting the same Error in the show() at the return dialog line. How to fix that ?
lateinit var dialog: CustomDialog
fun show(context: Context): Dialog {
return show(context, null)
}
fun show(context: Context, title: CharSequence?): Dialog {
if (::dialog.isInitialized) {
val inflater = (context as Activity).layoutInflater
val view = inflater.inflate(R.layout.progress_dialog_view, null)
if (title != null) {
view.cp_title.text = title
}
dialog = CustomDialog(context)
dialog.setContentView(view)
dialog.show()
}
return dialog
}
}
fun hideProgress() {
if (::dialog.isInitialized) {
if (dialog != null) {
dialog.dismiss()
}
}
Complete StackTrace :
kotlin.UninitializedPropertyAccessException: lateinit property dialog has not been initialized
at com.devApps.blog.CustomProgressDialog.show(CustomProgressDialog.kt:50)
at com.devApps.blog.PostActivity.upload(PostActivity.kt:328)
at com.devApps.blog.PostActivity.post(PostActivity.kt:320)
at com.devApps.blog.PostActivity.access$post(PostActivity.kt:54)
at com.devApps.blog.PostActivity$onCreate$5$2.onClick(PostActivity.kt:198)
If you close the activity without ever showing the dialog, this exception will happen. Because the dialog property in your CustomProgressDialog gets initialized only in show() method.
And onDestroy() method of the activity calls dismiss() on the dialog property that might not be initialized.
You can check if it's initialized first before dismissing it, consider adding this method inside CustomProgressDialog:
fun dismissDialog() {
if (::dialog.isInitialized) {
dialog.dismiss()
}
}
And call it from the activity:
override fun onDestroy() {
super.onDestroy()
progressDialognew.dismissDialog()
}

how to get callback between fragments in kotlin

I am trying to get a callback from one child fragment to parent fragment in kotlin and then later call a function in parent fragment to manage other layouts inside the child fragment.
I know how to get callback from a fragment to the activity and access the function in the fragment in the callback we cannot do that in Kotlin because of companion objects.
Another way is to pass context of fragment to child fragment and implement the interface using fragment's content in onAttach() but I cannot pass the context of parent fragment via constructor as I am using factory static methods.
Any help will be highly appreciated.
Child Fragment : DriverStatusFragment.kt
companion object {
#JvmStatic
fun newInstance() =
DriverStatusFragment().apply {
arguments = Bundle().apply {
}
}
}
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is OnCurrentOrderStatusChanged) {
orderStatusChangedCallBack = context
}
}
private fun handleUserOnlineStatus(isOnline: Boolean) {
CustomPreferences.setBooleanPreference(context!!, PrefEntity.IS_ONLINE, isOnline)
when (isOnline) {
true -> {
binding.idOnlineStatus.text = getString(R.string.online)
binding.idOnlineStatusImage.setImageResource(R.drawable.circle_green)
//testing:
orderStatusChangedCallBack?.orderStatusChanged(CONSTANTS.NEW_ORDER)
}
false -> {
binding.idOnlineStatus.text = getString(R.string.offline)
binding.idOnlineStatusImage.setImageResource(R.drawable.circle_gray)
}
}
}
Parent Fragment : HomeFragment.kt
class HomeFragment : Fragment(), OnMapReadyCallback, OnCurrentOrderStatusChanged {
companion object {
#JvmStatic
fun newInstance() =
HomeFragment().apply {
arguments = Bundle().apply {
}
}
}
fun handleOrderStatus(status: String) {
when (status) {
CONSTANTS.IDLE -> {
replaceFragment(
DriverStatusFragment.newInstance(),
DriverStatusFragment::class.java.simpleName
)
}
CONSTANTS.NEW_ORDER -> {
replaceFragment(
NewOrderFragment.newInstance(false),
NewOrderFragment::class.java.simpleName
)
}
CONSTANTS.ORDER_ACCEPTED -> {
replaceFragment(
EnRouteFragment.newInstance(CONSTANTS.ORDER_ACCEPTED),
EnRouteFragment::class.java.simpleName
)
}
CONSTANTS.ARRIVED_AT_DROP_LOCATION -> {
replaceFragment(
OrderDeliveredFragment.newInstance(CONSTANTS.ARRIVED_AT_DROP_LOCATION),
OrderDeliveredFragment::class.java.simpleName
)
}
CONSTANTS.DELIVERED -> {
replaceFragment(
DriverStatusFragment.newInstance(),
DriverStatusFragment::class.java.simpleName
)
}
}
override fun onAttach(context: Context) {
super.onAttach(context)
this.context = context
}
**NOT RECEIVING CALLBACK HERE**
override fun orderStatusChanged(orderStatus: String) {
CommonUtils.showToast(context!!, "REAched here")
handleOrderStatus(orderStatus)
}
}

How to set up a listener for a variable in Kotlin

How to I set up an interface listener for detecting a variable change in Kotlin. I successful implemented the following in Java, but am running into issues doing it in Kotlin:
Interface:
public interface InterfaceRefreshList
{
public void refreshListRequest();
}
Class containing listener:
public class SignalChange
{
private static boolean refreshListSwitch;
private static List<InterfaceRefreshList> refreshListListeners = new ArrayList<>();
public static void setRefreshList(boolean value)
{
refreshListSwitch = value;
for(InterfaceRefreshList l : refreshListListeners)
l.refreshListRequest();
}
public static void addRefreshListListener(InterfaceRefreshList l)
{
refreshListListeners.add(l);
}
}
Class where listener is listening:
public class FragmentBrowse extends Fragment
{
public FragmentBrowse() /// Constructor
{
SignalChange.addRefreshListListener(() -> refreshList());
}
refreshList()
{
// do something
}
}
To signal a change:
SignalChange.setRefreshList(true);
I can set up the interface and the signal class:
class SignalChange
{
private var refreshListSwitch: Boolean = false
var setSwitch: Boolean
get() = refreshListSwitch
set(value)
{
refreshListSwitch = value
}
private var refreshListListeners = ArrayList<InterfaceRefreshPersonsList>()
fun sendRefreshSignal()
{
for(l in refreshListListeners) l.refreshPersonsList()
}
fun addRefreshListListener(l: InterfaceRefreshPersonsList)
{
refreshListListeners.add(l)
}
}
But I cannot setup the listener in the FragmentBrowse class. The fragment class doesn't allow constructors.
You can use built-in Kotlin delegates, for example:
object SignalChange {
var refreshListListeners = ArrayList<InterfaceRefreshList>()
// fires off every time value of the property changes
var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
// do your stuff here
refreshListListeners.forEach {
it.refreshListRequest()
}
}
}
interface InterfaceRefreshList {
fun refreshListRequest()
}
Add listeners like this:
SignalChange.refreshListListeners.add(object : InterfaceRefreshList {
override fun refreshListRequest() {
refreshList()
}
})
OR
Intead of interface you can use lambda:
object SignalChange {
var refreshListListeners = ArrayList<() -> Unit>()
// fires off every time value of the property changes
var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
// do your stuff here
refreshListListeners.forEach {
it()
}
}
}
And to add listener just call:
SignalChange.refreshListListeners.add(::refreshList)
//or
SignalChange.refreshListListeners.add { refreshList() }
fun refreshList() {
}
The simple way to Listen to variable in KOTLIN
private var myVariableName by Delegates.observable(0) { property, oldValue, newValue ->
Log.d(TAG,"New Value $newValue")
Log.d(TAG,"Old Value $oldValue")
}
for more info read https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-delegates/

Android Kotlin - Create dialog inside a callback function

I'm trying to create a dialog inside a callback onSuccess() which again is inside the onCreate() method of the activity, but the dialog view doesn't show up.
When I call createDialog() directly inside the onCreate() it works. What could be the reason why it's not working in the onSuccess() callback function? onSuccess() and createDialog() definitely get called because the println show up.
Code:
class BleDevicesControlActivity : AppCompatActivity() {
private var device: BluetoothDevice? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ble_devices_control)
connectToDevice(object : BleCommunication.OnConnectionListener {
override fun onSuccess() {
println("onSuccess called")
createDialog()
}
override fun onFailure() {
println("onFailure called")
}
})
}
private fun connectToDevice(onConnectionListener : BleCommunication.OnConnectionListener) {
bleCommunication.connect(device!!, onConnectionListener)
}
private fun createDialog() {
println("createDialog called")
val dialogInflater = LayoutInflater.from(this)
val alertDialogView = dialogInflater.inflate(R.layout.dialog_alert, null)
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setView(alertDialogView)
alertDialog.show()
}
}
Try this
override fun onSuccess() {
println("onSuccess called")
runOnUiThread { createDialog() }
}
Set view to dialog builder:
private fun createDialog() {
println("createDialog called")
val dialogInflater = LayoutInflater.from(this)
val alertDialogView = dialogInflater.inflate(R.layout.dialog_alert, null)
val alertDialog = AlertDialog.Builder(this).setView(alertDialogView).create()
alertDialog.show()
}

MvvmCross custom binding display dialog

The goal is to display dialog for user to select date on tap on EditText.
I'm truing to implement binding that will show dialog on click. The code is the following:
public class EditDateBinding : BindingWrapper<EditText, DateTime>
{
public EditDateBinding(EditText androidControl) : base(androidControl)
{
}
public override void SubscribeToEvents()
{
Target.Click += InputClick;
}
private void InputClick(object sender, EventArgs args)
{
DateTime parsedDate = DateTime.Now;
DateTime.TryParse(Target.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out parsedDate);
var dialog = new DatePickerDialogFragment(Target.Context, parsedDate, OnDateSet);
dialog.Show(
// Can't get fragment manager here
, "date");
}
private void OnDateSet(object sender, DatePickerDialog.DateSetEventArgs e)
{
SetValueToView(Target, e.Date);
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (isDisposing)
{
if (Target != null)
{
Target.Click -= InputClick;
}
}
}
protected override void SetValueToView(EditText androidControl, DateTime value)
{
androidControl.Text = value.ToShortDateString();
}
}
But I cant find a way to get FragmentManager instance in order to call Show method of instantiated dialog. Can this be implemented in any way?
Found a way to implement it:
var act = (Activity) Target.Context;
dialog.Show(act.FragmentManager, "date");

Categories

Resources