I would like to help to fix a problem.
First, following the details of my code:
build.gradle (Project: android)
buildscript {
repositories {
jcenter()
mavenCentral()
maven { url '/home/melti/java/repository' }
}
dependencies {
classpath "com.android.tools.build:gradle:1.3.0-beta4"
classpath "com.android.databinding:dataBinder:1.0-rc0"
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
maven { url '/home/melti/java/repository' }
}
}
build.gradle (Module: app)
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'
android {
compileSdkVersion 22
buildToolsVersion "23.0.0 rc2"
defaultConfig {
applicationId "br.com.soma"
minSdkVersion 16
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.android.support:recyclerview-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.3'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.google.code.gson:gson:2.3.1'
compile 'org.springframework:spring-core:4.1.7.RELEASE'
compile 'org.apache.commons:commons-io:1.3.2'
}
AmanteEditModel
package br.com.soma.amante.edit;
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import br.com.soma.BR;
/**
* Created by spassu on 09/07/15.
*/
public class AmanteEditModel extends BaseObservable {
private String senhaConfirm;
@Bindable
public String getSenhaConfirm() {
return senhaConfirm;
}
public void setSenhaConfirm(String senhaConfirm) {
this.senhaConfirm = senhaConfirm;
notifyPropertyChanged(BR.senhaConfirm);
}
}
fragment_amante_edit
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto">
<data>
<variable name="model" type="br.com.soma.amante.edit.AmanteEditModel"/>
</data>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/card_edit_style"
android:layout_gravity="top"
card_view:cardCornerRadius="0dp">
<EditText
android:id="@+id/amante_edit_senha_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:hint="Confirme a senha"
android:inputType="textPassword"
android:maxLines="1"
android:text="@{model.senhaConfirm}"
/>
</android.support.v7.widget.CardView>
</ScrollView>
</layout>
AmanteEditFragment
package br.com.soma.amante.edit;
import android.app.Fragment;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import br.com.soma.R;
import br.com.soma.amante.view.AmanteViewActivity;
import br.com.soma.databinding.FragmentAmanteEditBinding;
/**
* Created by spassu on 27/05/15.
*/
public class AmanteEditFragment extends Fragment {
private AmanteEditModel model;
private static final String AMANTE_ID = "amanteId";
public static final String DEFAULT_FRAGMENT_TAG = "amanteEditFragment";
// Views
private long amanteId;
public AmanteEditFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
model = new AmanteEditModel();
FragmentAmanteEditBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_amante_edit, container, false);
binding.setModel(model);
return binding.getRoot();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_amante_edit, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
// The Save button was pressed
case R.id.menu_amante_edit_save:
save();
getActivity().finish();
return true;
}
return super.onOptionsItemSelected(item);
}
public static AmanteEditFragment newInstance(long id) {
AmanteEditFragment fragment = new AmanteEditFragment();
Bundle args = new Bundle();
args.putLong(AmanteViewActivity.EXTRA_AMANTEID, id);
fragment.setArguments(args);
return fragment;
}
private void save() {
Toast.makeText(getActivity(), model.getSenhaConfirm(), Toast.LENGTH_SHORT).show();
}
}
After enter data in senhaConfirm
and clickingsave(
), I found that the binding does not work, that is, the senhaConfirm
into AmanteEditModel
is null yet. Can anyone help me?
The Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically. Layouts are often defined in activities with code that calls UI framework methods.
Using data binding can lead to faster development times, faster execution times and more readable and maintained code. Android data binding generates binding classes at compile time for layouts.
EDIT: According to Remi David Android Studio now features two way databinding. The solution I describe below should no longer be nessesary.
Thanks Remi for pointing that out.
With respect to user input Android Databinding is only one way. The GUI will automagically reflect any changes in the model, but not vice versa.
You need to add a TextChangeListener to your model class which sets the model property when the user changes anything.
Example:
public class AmanteEditModel extends BaseObservable {
private String senhaConfirm;
@Bindable
public String getSenhaConfirm() {
return senhaConfirm;
}
public void setSenhaConfirm(String senhaConfirm) {
this.senhaConfirm = senhaConfirm;
notifyPropertyChanged(BR.senhaConfirm);
}
// Textwatcher Reference: http://developer.android.com/reference/android/text/TextWatcher.html
public TextWatcher getMyEditTextWatcher() {
return new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// Important! Use the property setter, otherwhise the model won't be informed about the change.
setSenhaConfirm(s);
}
};
}
}
In your layout xml change EditText to this:
<EditText
android:id="@+id/amante_edit_senha_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:hint="Confirme a senha"
android:inputType="textPassword"
android:maxLines="1"
android:text="@{model.senhaConfirm}"
app:addTextChangeListener="@{model.myEditTextWatcher}"
/>
Watch for the namespace of addTextChangeListener. This method might not be available through the android: namespace, so I'm using app: here. You may also use bind: to make the binding more clear.
So don't miss to add
xmlns:app="http://schemas.android.com/apk/res-auto"
or
xmlns:bind="http://schemas.android.com/apk/res-auto"
to your XML namespaces.
This solution works for all input controls, custom included, given you provide the correct Listeners in your model.
TextWatcher Reference
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With