How to use data-binding with Fragment
The data binding implementation must be in the onCreateView
method of the fragment, delete any data Binding that exist in your OnCreate
method,
your onCreateView
should look like this:
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
MartianDataBinding binding = DataBindingUtil.inflate(
inflater, R.layout.martian_data, container, false);
View view = binding.getRoot();
//here data must be an instance of the class MarsDataProvider
binding.setMarsdata(data);
return view;
}
DataBinding+ViewModel in Fragment Android Kotlin
Your ViewModel
and Fragment
does not have any connection
Do it like this:
BlankFragment:
private lateinit var vm: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vm = activity?.run {
ViewModelProviders.of(this)[MainViewModel::class.java]
} ?: throw Exception("Invalid Activity")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding: FragmentBlankBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_blank, container, false)
binding.viewmodel = vm//attach your viewModel to xml
return binding.root
}
}
ViewBinding in Fragment
This working fine for me:
private FragmentJavaPracticeBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentJavaPracticeBinding.inflate(inflater,container,false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
binding.notesRecyclerView.setVisibility(View.VISIBLE);//this hide/show recyclerview visibility
Log.d("TAG", "hidden: ");
}
Data binding from variable in fragment, android?
First way :
This not direct way which you asked. But you can also do using data class, this is little bit long way but you can add multiple data.
Make data class
data class Data(var struc: String = "Organization Structure")
Add this in xml
<data>
<variable
name="dataModel"
type="Data" /> // here data class path of step1
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.HomeFragment">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tvOrganization"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ivOrganization"
android:layout_marginTop="20dp"
android:gravity="center"
android:text="@{dataModel.struc}" // use like this
android:textAlignment="center"
android:textColor="@color/mountmerured"
android:textSize="15sp" />
</FrameLayout></layout>In Activity or fragment
private fun setData() {
val data = Data(struc= "Organization")
bindObject.dataModel = data
}
Second way :
Or Else direct way is
<data>
<variable
name="struc"
type="String" />
</data>
and from activity/fragment
bindObject.struc = "Organization Structure";
Third way :
Or In your case you need to do this in onCreateView and everything works
binding.data = this;
How to Intialize the Binding Properties in the Fragment to Make Two Way Data Binding Work
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.
Wht when I use view binding for fragment, my app crass without any reason?
In your adapter getView()
you are returning binding.root
which refers to the fragment layout binding. You should be returning menuRow.root
instead.
And you should have an exception in the logcat. Just make sure you don't have any logcat filters or such that hide it.
Related Topics
Message "Error: Resource Android:Attr/Lstar Not Found"
Android Drawerlayout - No Drawer View Found with Gravity
Fragment Lifecycle: When "Ondestroy" and "Ondestroyview" Are Not Called
How to Play an Mp3 in the Res/Raw Folder of My Android App
Android Opengl Es 2.0 Emulator
Broadcastreceiver as Inner Class
Android: Free Cropping of Image
Debug Native Code in Android Library
Write_Secure_Settings Permission Error Even When Added in Manifest
Android Get Activity Returns Null
Very Large Soap Response - Android- Out of Memory Error
How to Disable Home Button in Android
How to Attach Android Source to Eclipse
Android Sdk Cannot Be Found by Flutter
Android Activity Has Leaked Window Com.Android.Internal.Policy.Impl.Phonewindow$Decorview Issue