I have spent time to search to find the working solution. Some doesn't apply to my case and some doesn't work. That is why I am posting this here.
I am trying to pick a date using the DatePickerFragment in a fragment. I was following the directions explained in Android Developer's site here. I am not getting the code compiled even after following all the steps.
By the way, I am using Navigation Graph to switch between fragment.
Here is what I did and what I faced problem on:
My DatePickerFragment
class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val dayOfMonth = c.get(Calendar.DAY_OF_MONTH)
return DatePickerDialog(requireActivity(), this, year, month, dayOfMonth)
}
override fun onDateSet(view: DatePicker?, year: Int, month: Int, day: Int) {
// Do something with the date chosen by the user
// I want to update the button text of my AddNewTransactionFragment with the date picked
}
}
My AddNewTransactionFragment
The supportFragmentManager is not recognized.
class AddNewTransactionFragment : Fragment(R.layout.fragment_add_new_transaction) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fun showDatePickerDialog(v: View) {
val newFragment = DatePickerFragment()
newFragment.show(supportFragmentManager, "datePicker")
// here this 'supportFragmentManager' is red and the code won't compile with the
// error: Unresolved reference: supportFragmentManager.
// and the function showDatePickerDialog is grayed out even though I have
// android:onClick="showDatePickerDialog" in the corresponding xml file.
}
}
}
My xml file of fragment AddNewTransactionFragment
Here, the button android:onClick= attribute has a method but it is red, which is not recognized from the Fragment code.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/backgroundGray"
android:padding="25dp"
tools:context="com.sukajee.splitexpense.AddNewTransactionFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textViewAddNew"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:text="Add New Transaction"
android:textColor="#color/colorAccent"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textViewTransactionDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:text="Date"
android:textColor="#color/colorAccent"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/textViewAddNew" />
<Button
android:id="#+id/buttonTransactionDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Friday, 01 January 2021"
app:layout_constraintStart_toStartOf="parent"
android:onClick="showDatePickerDialog"
app:layout_constraintTop_toBottomOf="#id/textViewTransactionDate" />
<EditText
android:id="#+id/editTextDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ellipsize="end"
android:hint="Description (Grocery, Food, Laundry etc.)"
android:maxLines="1"
android:textColorHint="#color/colorAccent"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/buttonTransactionDate" />
<EditText
android:id="#+id/editTextStore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ellipsize="end"
android:hint="Store Name"
android:maxLines="1"
android:textColorHint="#color/colorAccent"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/editTextDescription" />
<EditText
android:id="#+id/editTextAmount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ellipsize="end"
android:hint="Amount"
android:inputType="numberDecimal"
android:maxLines="1"
android:textColorHint="#color/colorAccent"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/editTextStore" />
<EditText
android:id="#+id/editTextNote"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ellipsize="end"
android:hint="Note"
android:inputType="textMultiLine"
android:textColorHint="#color/colorAccent"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/editTextAmount" />
<Button
android:id="#+id/buttonSubmit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Submit"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/editTextNote" />
<Button
android:id="#+id/buttonCancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Cancel"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/buttonSubmit" />
<Button
android:id="#+id/buttonClear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Clear"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/buttonCancel" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
This is what explained in the developer's site. What could be the reason for me not getting the required output even after following everything described?
Please help.
You are trying to use the supportFragmentManager from a Fragment but the supportFragmentManager is only available from an Activity specifically an AppCompatActivity or FragmentActivity.
From a Fragment you could use the childFragmentManager as a FragmentManager but i've never tried to open a DialogFragment from a Fragment.
You have used supportFragmentManager which is available in activity, and also you wrote a method inside another method.
Try with this.
class AddNewTransactionFragment : Fragment(R.layout.fragment_add_new_transaction) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
someButton.setOnClickListener{v->showDatePickerDialog(v)}
}
fun showDatePickerDialog(v: View) {
val newFragment = DatePickerFragment()
newFragment.show(childFragmentManager, "datePicker")
// here this 'childFragmentManager' is red and the code won't compile with the
// error: Unresolved reference: supportFragmentManager.
// and the function showDatePickerDialog is grayed out even though I have
// android:onClick="showDatePickerDialog" in the corresponding xml file.
}
}
Related
This code is where I am creating Alert dialog. whenever I press ok it crashes .password_dialog has 1 editText and 2 buttons.
private fun passwordCheck(position: Int){
val view=LayoutInflater.from(requireContext()).inflate(R.layout.password_dialog,null,false)
val builder=AlertDialog.Builder(requireContext())
with(builder){
setTitle("Enter your Pin")
setPositiveButton("Ok"){dialog,which->
if(pin_text.text.toString()=="1234"){
Toast.makeText(requireContext(),"Right Pin",Toast.LENGTH_LONG).show()
}
else{
pin_text.requestFocus()
pin_text.error="Incorrect"
}
}
setCancelable(false)
setNegativeButton("Cancel"){dialog,which->
dialog.dismiss()
}
setView(view)
show()
}
}
Create a layout with the view, for example, an EditText that only accepts numbers and two buttons, accept or cancel.
Then inflate the view
val view = LayoutInflater.from(context).inflate(R.id.layout, null, false)
Then with that view you get the reference of the buttons and the EditText with
val button = view.findViewById<Button>(R.id.button)
//I'm not going to declare all views, but assuming you already did.
button.setOnClickListener {
if (editText.text.toString.toInt() == 1234 //your correct pin) {
//CORRECT PIN TODO
} else {
editText.requestFocus()
editText.error = "Incorrect pin"
}
}
Then create the dialog and add that view to it
AlertDialog.Builder(context).setView(view).create().show()
Do not add the validation methods in the accept button of the dialog.
They are what are declared as follows.
setPositiveButton("Accept"){diálog, which -> }
This is the way by which you can create your own dialog with custom layout.
Implement your PIN UI in custom_dialog.xml and your logic in Kotlin file.
Here is example how you can create custom Dialog.
custom_dialog.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#424242">
<TextView
android:id="#+id/popup_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16sp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16sp"
android:layout_marginBottom="10dp"
android:text="Custom Dialog Box"
android:textColor="#color/white"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/linearLayoutOpt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16sp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16sp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/popup_dialog">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal">
<TextView
android:id="#+id/no_opt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingTop="8dp"
android:paddingRight="8dp"
android:paddingBottom="18dp"
android:text="No"
android:textStyle="bold"
android:textAllCaps="false"
android:textColor="#color/white" />
<Space
android:layout_width="32sp"
android:layout_height="12sp" />
<TextView
android:id="#+id/yes_opt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingTop="8dp"
android:paddingRight="8dp"
android:paddingBottom="18dp"
android:text="Yes"
android:textStyle="bold"
android:textAllCaps="false"
android:textColor="#color/white" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showDialog()
}
private fun showDialog() {
val customDialog = Dialog(this)
customDialog.setContentView(R.layout.custom_dialog)
customDialog.window?.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val yesBtn = customDialog.findViewById(R.id.yes_opt) as TextView
val noBtn = customDialog.findViewById(R.id.no_opt) as TextView
yesBtn.setOnClickListener {
//Do something here YOUR LOGIC
customDialog.dismiss()
}
noBtn.setOnClickListener {
customDialog.dismiss()
}
customDialog.show()
}
}
example app screenshot
I would like to change color of one element in recyclerview on action(for example swipe, but it works fine).
I have used:
viewHolder!!.itemView.setBackgroundColor(Color.GRAY)
It works like on screen, because I have different layout like layout_content.
Gray coolor in wrong place
When I add line like below color doesn't change at all. Please notice, that I had to implement another binding with other layout which uses another .xml file to get some preferences.
layoutBinding.vContent.frameLayout.setBackgroundColor(Color.GREY)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bg_list_item_incoming_leads"
android:paddingBottom="#dimen/spacing_2"
app:cardCornerRadius="#dimen/spacing_8">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/btnClose"
style="?android:borderlessButtonStyle"
android:layout_width="#dimen/spacing_32"
android:layout_height="#dimen/spacing_32"
android:layout_gravity="end"
android:layout_marginTop="20dp"
android:layout_marginEnd="#dimen/spacing_16"
android:contentDescription="#string/notification_list_close_button_content_description"
android:src="#drawable/ic_icon_grey_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="TouchTargetSizeCheck" />
<TextView
android:id="#+id/tvLeadFullName"
style="#style/Regular.13"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="6dp"
android:layout_marginBottom="2dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tvSimpleText"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvInformation"
app:layout_constraintVertical_chainStyle="spread_inside"
tools:text="%leadfullname" />
<TextView
android:id="#+id/tvProductNotification"
style="#style/Regular.13"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:layout_marginStart="6dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="2dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/tvSimpleText"
app:layout_constraintTop_toBottomOf="#+id/tvInformation"
app:layout_constraintVertical_chainStyle="spread_inside"
tools:text="%product" />
<TextView
android:id="#+id/tvSimpleText"
style="#style/Regular.13"
android:layout_width="wrap_content"
android:layout_height="27dp"
android:layout_marginStart="6dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="6dp"
android:layout_marginBottom="2dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tvProductNotification"
app:layout_constraintStart_toEndOf="#+id/tvLeadFullName"
app:layout_constraintTop_toBottomOf="#+id/tvInformation"
app:layout_constraintVertical_chainStyle="spread_inside"
tools:text="-" />
<TextView
android:id="#+id/tvInformation"
style="#style/Regular.15"
android:layout_width="211dp"
android:layout_height="27dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread_inside"
tools:text="You received a new Lead" />
<TextView
android:id="#+id/tvData"
style="#style/Regular.13"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="10dp"
android:textColor="#color/black"
app:layout_constraintEnd_toStartOf="#+id/btnClose"
app:layout_constraintTop_toTopOf="parent"
tools:text="11 Oct 2021" />
<TextView
android:id="#+id/tvTime"
style="#style/Regular.13"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btnClose"
tools:text="hh:ss" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#color/white">
</solid>
<corners
android:topRightRadius="#dimen/spacing_8"
android:topLeftRadius="#dimen/spacing_8"
android:bottomLeftRadius="#dimen/spacing_8"
android:bottomRightRadius="#dimen/spacing_8">
</corners>
</shape>
How to have access to .xml file and change background from fragment directly to bg_list_item_incoming_leads.xml maybe that would be a solution?
EDIT, additional information:
BaseFragment
abstract class BaseFragmentBindings<VB : ViewBinding, LB : ViewBinding, VM : BaseViewModel>(private val inflate: Inflate<VB>, private val secondInflate: Inflate<LB>) :
Fragment() {
private var binding: VB? = null
protected val layout: VB
get() = binding!!
private var bindingLayout: LB? = null
protected val layoutBinding: LB
get() = bindingLayout!!
abstract val vm: VM
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = inflate.invoke(inflater, container, false)
bindingLayout = secondInflate.invoke(inflater, container, false)
return binding!!.root
}
fragment
#AndroidEntryPoint
class NotificationListFragment :
BaseFragmentBindings<FragmentNotificationListBinding, LayoutListItemNotificationBinding, NotificationListViewModel>
(FragmentNotificationListBinding::inflate, LayoutListItemNotificationBinding::inflate) {
override val vm: NotificationListViewModel by viewModels()
...
}
try below snippet, get reference to background, which is Drawable, check if its ColorDrawable (in your case it is set only in XML then it will always be) and if is then use class casting and set new color, other params should stay unchanged (like rounded corners set with <corners tag, btw. app:cardCornerRadius="#dimen/spacing_8" in main XML set for FrameLayout is no-op, it was left there probably when this item was a CardView)
Drawable background = layoutBinding.vContent.frameLayout.getBackground();
if (background instanceof ColorDrawable)
((ColorDrawable) background).setColor(Color.GRAY);
So I'm doing a project and I'm completely lost. I have seen how to do data binding with TextViews but I am being asked to do it with EditText Views with Two Way Data Binding. I got up to here so far with it.
The XML File.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="myShoe"
type="com.udacity.shoestore.product.Shoe" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<TextView
android:id="#+id/title_detail_view"
style="#style/title_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="80dp"
android:text="#string/add_shoe_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/shoe_name"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="#string/shoe_name_string"
android:inputType="text"
android:textSize="30sp"
android:text="#={myShoe.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_detail_view" />
<EditText
android:id="#+id/shoe_size"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/size_string"
android:inputType="number|numberDecimal"
android:textSize="15sp"
android:text="#={myShoe.size}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shoe_name" />
<EditText
android:id="#+id/company_name"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/company_string"
android:inputType="text"
android:textSize="15sp"
android:text="#={myShoe.company}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shoe_size" />
<EditText
android:id="#+id/shoe_description"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/description_string"
android:inputType="text"
android:textSize="15sp"
android:text="#={myShoe.description}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/company_name" />
<Button
android:id="#+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#color/colorPrimaryDark"
android:text="#string/cancel_string"
android:textColor="#android:color/white"
app:layout_constraintBaseline_toBaselineOf="#+id/savee_button"
app:layout_constraintEnd_toStartOf="#+id/savee_button"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/savee_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="88dp"
android:backgroundTint="#color/colorPrimaryDark"
android:text="#string/save_string"
android:textColor="#android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shoe_description" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
I was told to implement it to a fragment and it should work. But I'm not sure how. Here's the fragment
class ShoeDetailsFragment : Fragment() {
private val viewModel: ActivityViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentShoeDetailsBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_shoe_details,
container, false
)
//initializing the button and clearing the views once canceled
binding.cancelButton.setOnClickListener { v: View ->
v.findNavController().navigateUp()
binding.shoeName.text.clear()
binding.shoeSize.text.clear()
binding.companyName.text.clear()
binding.shoeDescription.text.clear()
}
//initializing the button and saving the info to transfer to the shoeList
binding.saveeButton.setOnClickListener { v: View ->
v.findNavController().navigateUp()
val name = shoe_name.text.toString()
val size = shoe_size.text.toString()
val brand = company_name.text.toString()
val details = shoe_description.text.toString()
viewModel.addShoe(name, size, brand, details)
}
return binding.root
}
}
I am open to any ideas to initialize binding properties so i can use it in both the layout and the fragment. Or am I looking at this the wrong way?
P.S. The XML File is being represented in this fragment
I also did this project for my NanoDegree.
Inside my ViewModel I created 3 variables for each EditText:
MutableLiveData - to update the value inside the viewModel
LiveData to expose value outside viewModel e.g. in a fragment (you won't really need this)
Public Variable to monitor value of MutableLiveData and expose this to your xml thus achieving the 2-Way Binding.
Then I and would create a Shared ViewModel to share data between ShoeDetailsFragment and ShoeListingFragment .
Inside the SharedViewModel
I created 3 variables for each EditText (this is just the first 2 Edittexts):
class MySharedViewModel : ViewModel() {
private val _name = MutableLiveData<String>()
val name: LiveData<String>
get() = _name
var edShoeName = ""
private val _size = MutableLiveData<Double>()
val size: LiveData<Double>
get() = _size
var edSize = ""
......}
For the xml I did exactly what you have done but used the 3rd variable for the 2-Way Data Binding:
<EditText
android:id="#+id/shoe_name"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:ems="10"
android:hint="#string/shoe_name_string"
android:inputType="text"
android:textSize="30sp"
android:text="#={mySharedViewModel.edShoeName}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_detail_view" />
<EditText
android:id="#+id/shoe_size"
style="#style/login_style"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/size_string"
android:inputType="number|numberDecimal"
android:textSize="15sp"
android:text="#={mySharedViewModel.edCompany}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shoe_name" />
I have seen you have included this line of code on your ShoeDetailFragment code:
binding.saveeButton.setOnClickListener { v: View -> ....}
In my case I did it inside SharedViewModel instead:
fun onSaveButtonClick() {
//check value entered for size and set it to 0 if blank
if (edSize == "") {
edSize = "0"
}
//update MutableLiveData with values read live from the EditText
_name.value = edShoeName
_size.value = edSize.toDouble()
//save shoeObject to the _shoeList MutableLiveData
_shoeList.value?.add(Shoe(edShoeName, edSize.toDouble(), edCompany, edDescription))
}
Using DataBinding I moved the onClick bit to xml:
<Button
android:id="#+id/buttonSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="75dp"
android:layout_marginBottom="75dp"
android:background="#drawable/custom_button_background"
android:onClick="#{()->sharedViewModel.onSaveButtonClick()}"
You can also refer to my project.
So I'm fairly new to Kotlin.
I am trying to create an onClickListener on an image button to open the share interface, so that the particular video from the recyclerView can be shared via SMS, etc.
I followed various tutorials on how to do this as I am trying to execute this within a fragment, and the app just keeps crashing when I try to open the fragment in question.
I get the following error
java.lang.ClassCastException: java.lang.Integer cannot be cast to android.widget.ImageButton
Here is what my fragment code looks like:
SearchFragment.kt
class SearchFragment : Fragment(), View.OnClickListener
{
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<ClipAdapter.ViewHolder>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View
{
val rootView = inflater.inflate(R.layout.fragment_search, container, false)
loadData()
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
val shareBtn = view.findViewById<ImageButton>(R.id.button_to_share)
shareBtn.setOnClickListener(this)
}
private fun loadData()
{
val service = TwitchServiceBuilder.buildService(TwitchService::class.java)
val requestCall = service.getClips("anerdfails")
requestCall.enqueue(object : Callback<List<Clip>>
{
override fun onResponse(
call: Call<List<Clip>>,
response: Response<List<Clip>>
)
{
if (response.isSuccessful)
{
//process data
recyclerView.layoutManager = GridLayoutManager(activity, 2)
recyclerView.adapter = ClipAdapter(response.body()!!)
} else
{
//output alert
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("Response, but something went wrong ${response.message()}")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
}
override fun onFailure(call: Call<List<Clip>>, t: Throwable)
{
//process failure
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("No response, and something went wrong $t")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
})
}
override fun onClick(v: View?)
{
Toast.makeText(activity, "Its toast!", Toast.LENGTH_SHORT).show()
}
}
And here are my 2 layouts for the RecyclerView:
fragment_search.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="15dp"
android:paddingTop="?attr/actionBarSize"
android:paddingEnd="15dp"
tools:context=".ui.search.SearchFragment">
<androidx.appcompat.widget.SearchView
android:background="#drawable/search_bar"
android:id="#+id/clipSearch"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="5dp"
android:focusable="true"
android:focusableInTouchMode="true"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="75dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/clipSearch" />
</androidx.constraintlayout.widget.ConstraintLayout>
clip_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".ui.search.SearchFragment">
<VideoView
android:id="#+id/videoClip"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintDimensionRatio="w,2:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoClip"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtChannel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtTitle"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtGame"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtChannel"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtViews"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtGame"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal"
android:weightSum="2"
android:layout_marginTop="15dp"
app:layout_constraintTop_toBottomOf="#+id/txtViews">
<ImageButton
android:id="#+id/favouriteButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_favorite_border_24" />
<ImageButton
android:id="#+id/button_to_share"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_share_24" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Seems like a simple mistake on my part, but I'm pulling my hair out trying to work out what I've done wrong to cause the error on loading.
Any help would be appreciated.
I see you're trying to find the button "ShareBtn" inside the fragment which is totally wrong.
the "ShareBtn" doesn't belong to the fragment, it belongs to the viewHolder which you have created inside "ClipAdapter"
What you need to do is creating an interface inside "ClipAdapter" and create an object from it inside the Adapter
then call the method which is should the clickListener delegates the click to it
lastly, you should implement it inside the fragment and put whatever logic you want
This link will help you implement it
You are casting ID of view which is an Integer to ImageButton which is a View in this line
val shareBtn = R.id.button_to_share as ImageButton
You should use this instead
val shareBtn = findViewById<ImageButton>(R.id.button_to_share)
UPDATE
Also you should find views after fragment view got created. It means you should call `findViewById` inside `onViewCreated` and not inside `onCreateView`. If you try to find views before view of fragment gets created then you get `NullPointerException` since there is no view yet.
i'm trying to write my very first android app. the only programing i have done in the past was some html 4 many years ago (before cms was a thing)
it is essentially a check list but i want to be able to have multiple lists seperated by a list name supplied by the user. i have an input text box called "island name" but i cant figure out how to capture that text from the user and save it for future use...
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="189dp"
android:text="temp call islander page"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="125dp"
android:layout_marginBottom="271dp"
android:onClick="loadHome"
android:text="home"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="41dp"
android:ems="10"
android:hint="island name"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="7dp"
android:layout_marginBottom="8dp"
android:text="north"
app:layout_constraintBottom_toTopOf="#+id/checkBox2"
app:layout_constraintEnd_toEndOf="#+id/checkBox2" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginBottom="88dp"
android:text="south"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/editText" />
println("your island name is $name")
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="19dp"
android:text="you entered $name"
app:layout_constraintStart_toEndOf="#+id/checkBox2"
app:layout_constraintTop_toBottomOf="#+id/checkBox2" />
</androidx.constraintlayout.widget.ConstraintLayout>
To put it simply, in Android dev (Android Studio) you have your view, which is your .xml file and your program logic is written in your .kt or .java file then you refer to your respective view from the .kt oe ,java file.
e.g
activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/textView"
android:layout_height="wrap_content"
android:layout_width="200dp"/>
<Button
android:id="#+id/saveBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save" />
</LinearLayout>
MainActivity.kt :
import kotlinx.android.synthetic.main.activity_main.* //this will reference all views in activity_main -
//Android studio usually auto imports this when you simply type control name
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
saveBtn.setOnClickListener {
saveDetails()
}
}
fun saveDetails(){
var userText = textView.text.toString()
textView4.setText(userText)
//do something with text
}
}
For those who is experiencing the same issue you can use sharedPreferences. As an example:
private lateinit var sp: SharedPreferences
private lateinit var editor: SharedPreferences.Editor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
nameEditText = findViewById(R.id.etName)
ageEditText = findViewById(R.id.etAge)
sp = getSharedPreferences("my_sf", MODE_PRIVATE)
editor = sp.edit()
}
override fun onPause() {
super.onPause()
val name = nameEditText.text.toString()
val age = ageEditText.text.toString().toInt()
editor.apply {
putString("my_name", name)
putInt("my_age", age)
commit()
}
}
override fun onResume() {
super.onResume()
val name = sp.getString("my_name", null)
val age = sp.getInt("my_age", 0)
nameEditText.setText(name)
if (age!=0) ageEditText.setText(age.toString())
}