I am not sure why I cannot update the imageView of a custom dialog layout xml which is opened from inside a fragment.
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(R.layout.qr_code_layout_dialog);
imageFromLayout.setImageBitmap(myBitmap);
builder.show();
I have also tried to use a Dialog object (not AlertDialog) but it will not even open, therefore AlertDialog opens but will not show any images. Nor will it allow me to update the images from within the java code.
How can I update the imageView image of the layout dialog from within the fragment?
You can try make realisation of it
abstract class ObservableDialog<T>(private val callBack: (T) -> Unit): DialogFragment(){
companion object{
const val TAG = "MY_TAG"
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return super.onCreateView(inflater, container, savedInstanceState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setLayoutParam()
}
fun doMyChoice(obj: T){
callBack(obj)
dismiss()
}
private fun setLayoutParam(){
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
}
}
Call it like
val dialog = ObservableDialog<String>{
//do something with result
}
dialog.show(supportFragmentManager, ObservableDialog.TAG)
Related
I have a custom dialog in kotlin fragment which have 2 button and a progress bar in fuction submitSpk()
class RincianPembelianFragment : androidx.fragment.app.Fragment(), BlockingStep {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater.inflate(R.layout.fragment_spk_rincian_bayar, container, false)
//initialize your UI
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.supportFragmentManager?.popBackStack(null, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE)
setContext(activity!!.applicationContext)
}
fun submitSpks (){
val inflater = context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val builder = AlertDialog.Builder(context!!)
val dialogView = inflater.inflate(R.layout.activity_signature, null)
builder.setView(dialogView)
builder.setTitle("Tanda Tangan Pembeli")
//builder.show()
builder.setCancelable(false)
dialogView.clear.setOnClickListener {
dialogView.signature_view.clearCanvas()
}
dialogView.save.setOnClickListener {
submitTtd() // or some fuction else
dialogView.save.visibility = View.INVISIBLE
dialogView.progressBar.visibility = View.VISIBLE
}
builder.setNegativeButton(""){ dialog: DialogInterface?, which: Int ->
}
builder.show()
}
fun submitTtd(){
// here there will be a crud transaction and visible/invisible button save
}
}
my custom dialog is look like this
i want to visibility gone the button save dialogView.save.visibility = View.VISIBLE from another fuction e.g saveTtd()
how can i do this? i have tried this but my dialog can't show.. anyone can help me? Thanks before
Storing the dialogView in a global variable should do the job.
Also, call the build() method on the AlertDialog.Builder instance before showing the dialog:
class RincianPembelianFragment : androidx.fragment.app.Fragment(), BlockingStep {
private lateinit var dialogView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater.inflate(R.layout.fragment_spk_rincian_bayar, container, false)
//initialize your dialog view
dialogView = inflater.inflate(R.layout.activity_signature, null)
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.supportFragmentManager?.popBackStack(null, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE)
setContext(activity!!.applicationContext)
}
fun submitSpks() {
// Using requireContext() is suggested
val builder = AlertDialog.Builder(requireContext())
builder.setView(dialogView)
builder.setTitle("Tanda Tangan Pembeli")
builder.setCancelable(false)
dialogView.clear.setOnClickListener {
dialogView.signature_view.clearCanvas()
}
dialogView.save.setOnClickListener {
submitTtd() // or some fuction else
}
builder.setNegativeButton(""){ dialog: DialogInterface?, which: Int ->
}
// Build the dialog builder before showing it
val dialog = builder.build()
dialog.show()
}
fun submitTtd(){
// here there will be a crud transaction and visible/invisible button save
dialogView.save.visibility = View.INVISIBLE
dialogView.progressBar.visibility = View.VISIBLE
}
}
I am looking to send a string from FragmentA to FragmentDialog by means of an interface Communicator through my Main Activity (which automatically opens FragmentDialog). Some code to illustrate what I have:
class FragmentA: Fragment() {
private lateinit var communicator: Communicator
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_A, container, false)
val title = "My Title"
button.setOnClickListener { communicator.passData(title) }
return view
}
}
class FragmentDialog : DialogFragment() {
var title: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.dialog, container, false)
view.button_close.setOnClickListener { dismiss() }
title = arguments?.getString("title")
view.dialog_title.text = title
return view
}
}
interface Communicator {
fun passData (titleInput: String)
}
and in my Main Activity, which extends the interface:
private val fragmentDialog = FragmentDialog()
override fun passData(titleInput: String) {
val bundle = Bundle()
bundle.putString("title", titleInput)
fullScreenDialog.arguments = bundle
val transaction = supportFragmentManager.beginTransaction().add(android.R.id.content, fragmentDialog).addToBackStack(null).commit()
}
When I click the button in FragmentA, I want to send the string title to Communicator, set the XML element with id dialog_title in FragmentDialog and automatically open the fragment. In fact, this works fine. The issue is that my "back button" in FragmentDialog, i.e. view.button_close.setOnClickListener { dismiss() } only works exactly once. If I click button in FragmentA again, FragmentDialog opens fine with the correct title still but button_close no longer dismisses the dialog. What could be causing this? I am not getting any consol errors.
I want to set the drawable of a ImageView and a ProgressBar in a DialogFragment at runtime. Therefore i want to set the drawable in the onViewCreated and set the ProgressBar visible when the Positive Button of the Dialog is clicked.
But for reasons i do not know absolutely nothing happens. i also tried to call invalidate on the view to actively trigger a redraw but also nothing happens.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.dialog_view, container, false)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val inflater = requireActivity().layoutInflater
val layout = inflater.inflate(R.layout.dialog_view, null)
val dialog = AlertDialog.Builder(requireContext())
.setTitle(R.string.dialog_title)
.setMessage(R.string.dialog_text)
.setView(layout)
.setPositiveButton(R.string.start, null)
.setNegativeButton(R.string.cancel, null)
.create()
return dialog
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageView.setImageDrawable(image) //image is a drawable
}
override fun onResume() {
super.onResume()
val d = dialog as AlertDialog?
d?.getButton(Dialog.BUTTON_POSITIVE)?.setOnClickListener {
progressBar.visibility = View.VISIBLE
}
}
Edit:
Found out that if i directly call something on the layout i pass to the dialog it is possible to change visibility of views.
val layout = inflater.inflate(R.layout.dialog_view, null)
layout.findViewById ....
This works but i still wonder why i cannot simply call with kotlin synthetics on the view.
The action that you want to be performed when the positive button is pressed should be added in the dialog build
.setPositiveButton(R.string.start){ _, _ ->
progressBar.visibility = View.VISIBLE
}
I've tried to invoke DialogFragment from custom view:
DetailsDialogFragment
.newInstance(newSelectedDate, adapterItems[newPosition].progress)
.apply {
show(childFragmentManager, SCORE_DETAILS_DIALOG_TAG)
}
where DetailsDialogFragment looks like this:
class DetailsDialogFragment : AppCompatDialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return requireActivity().let {
val dialog = Dialog(requireContext(), R.style.CustomDialog)
dialog.window?.setDimAmount(BaseDialogFragment.SCRIM_OPACITY)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialog
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_details_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.rootView.apply {
findViewById<TextView>(R.id.titleTextView).text = arguments?.getString(ARGS_MONTH)
findViewById<ActionButton>(R.id.button).setOnClickListener {
dismiss()
}
findViewById<ImageView>(R.id.closeImageView).setOnClickListener {
dismiss()
}
}
}
companion object {
fun newInstance(
month: String,
score: Int
): DetailsDialogFragment {
return DetailsDialogFragment()
.apply {
arguments = bundleOf(
ARGS_MONTH to month,
ARGS_SCORE to score
)
}
}
}
}
But I receive the following error:
IllegalStateException: Fragment DetailsDialogFragment has not been attached yet.
at androidx.fragment.app.Fragment.getChildFragmentManager(Fragment.java:980)
...
Is it possible to invoke DialogFragment from custom view at all?
The reason of this exception is that you're trying to use the childFragmentManager of your freshly newly created instance, which is of course not possible since the Dialog fragment hasn't yet has its internals initialized yet (including its childFragmentManager).
If you're using AndroidX I'd use the findFragment extension method inside your custom view and try to do:
Inside your custom view
val dialogFragment = DetailsDialogFragment
.newInstance(newSelectedDate, adapterItems[newPosition].progress)
dialogFragment.show(findFragment().childFragmentManager, SCORE_DETAILS_DIALOG_TAG)
In my application i want use fragment and i want show Toast message just when users see this fragment show message.
I write below codes but when show fragment not show me any Toast!
In java i haven't any issue and show Toast, but when use kotlin not show Toast!
My codes:
class TestFragment : Fragment() {
private val title by lazy { arguments?.getString("title") ?: "" }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_test, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
testFragText.text = title
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (isVisibleToUser){Toast.makeText(context, "Show", Toast.LENGTH_SHORT).show()}
}
}
How can i fix it?