I've got a problem with databinding in android.
Above are xml file and activity class:
activity_main.xml ( the binding is in android:enabled="#{loginInfo.existingUser}")
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="loginInfo"
type="com.example.android.loginapplication.LoginInfo"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/new_customer"
android:enabled="#{loginInfo.existingUser}"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/i_have_a_password"/>
</RadioGroup>
<EditText
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"/>
</LinearLayout>
</layout>
LoginInfoActivity.java
public class LoginInfoActivity extends AppCompatActivity {
private LoginInfo loginInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LoginInfoBinding binding = DataBindingUtil.setContentView(
this, R.layout.activity_main);
binding.setLoginInfo(loginInfo);
}
}
it can't find generated class LoginInfoBinding in LoginInfoActivity...
is the xml correct? Or it depends by other things?
The binding class is named after the layout resource by default. Your layout resource is activity_main.xml, so the binding is ActivityMainBinding.
Related
So I have my RecyclerView setup with ViewDataBinding and I'm showing a ProgressBar on click of a button inside the item. The ProgressBar shows and pops a dialog, on cancelling dialog I can notifyItemChanged to hide the ProgressBar, it only works the first time.
Here is my layout of the item:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<import type="android.view.View"/>
<variable
name="inProgress"
type="boolean" />
<variable
name="userModel"
type="com.smartsco.recaru.room.dataModels.UserModel" />
<variable
name="messageModel"
type="com.smartsco.recaru.room.dataModels.MessageModel" />
<variable
name="clickHandler"
type="com.smartsco.recaru.interfaces.OnClickHandler" />
</data>
<RelativeLayout
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:paddingTop="8dp"
android:paddingBottom="8dp">
<androidx.cardview.widget.CardView
android:id="#+id/ll_invoice"
android:layout_width="#dimen/ml_invoice_width"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="8dp"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
app:cardBackgroundColor="#color/bg_ml_invoice"
app:cardCornerRadius="2dp"
app:cardElevation="3dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/bg_ml_invoice"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="4dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/ll_invoice_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal"
android:padding="8dp"
android:visibility="#{!inProgress && messageModel.InvoiceData.status.equalsIgnoreCase(`pending`) ? View.VISIBLE : View.INVISIBLE}"
android:weightSum="2">
<Button
style="#style/Button_Invoice_Positive"
android:id="#+id/btn_agree"
android:layout_width="match_parent"
android:layout_height="#dimen/btn_invoice_height"
android:layout_weight="1"
android:text="#string/agree"
android:onClick="#{(v)-> clickHandler.onClick(v)}"/>
<Space
android:layout_width="6dp"
android:layout_height="0dp"/>
<Button
android:id="#+id/btn_disagree"
style="#style/Button_Invoice_Negative"
android:layout_width="match_parent"
android:layout_height="#dimen/btn_invoice_height"
android:layout_weight="1"
android:text="#string/disagree"
android:onClick="#{(v)-> clickHandler.onClick(v)}" />
</LinearLayout>
<ProgressBar
android:id="#+id/pb_invoice"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerInParent="true"
android:padding="8dp"
android:visibility="#{inProgress ? View.VISIBLE : View.INVISIBLE}" />
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
</layout>
Here is how the ViewHolder looks like:
private class InvoiceMessageHolder extends RecyclerView.ViewHolder implements OnClickHandler {
private RowRecyclerViewChatInvoiceMessageBinding binding;
InvoiceMessageHolder(RowRecyclerViewChatInvoiceMessageBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bind(MessageModel message, UserModel userModel) {
binding.setMessageModel(message);
binding.setUserModel(userModel);
binding.setClickHandler(this);
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_agree:
case R.id.btn_disagree:
binding.setInProgress(true);
invoiceClickHandler.onClick(v, getAdapterPosition(), binding.getMessageModel());
break;
}
}
}
as you can see I have created a variable inside the layout itself to toggle inProgress boolean which works perfectly except won't reset itself on 2nd call of notifyItemChanged.
Another weird behaviour I have witnessed is that sometimes I click on button inside one item and it shows progress bar in all the viewholders for that itemViewType.
P.S.On calling notifyItemChanged, the view animates as if it was notified of a change but is only effective the first time.
Thanks
Dependency reference: journeyapps/zxing-android-embedded
Description of the problem:
I'm new to Android Data binding & cannot bind the resource id zxing_viewfinder_view which is inside <merge> </merge>
Here is my code for understanding.
activity_scan_qr.xml
<LinearLayout
android:id="#+id/ll_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_below="#+id/ll_header"
android:background="#color/color_white"
android:gravity="center"
android:orientation="vertical">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="#+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_scanner_layout="#layout/view_custom_qr_scanner"/>
</LinearLayout>
view_custom_qr_scanner.xml
<?xml version="1.0" encoding="utf-8"?>
<merge 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">
<com.journeyapps.barcodescanner.BarcodeView
android:id="#+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_framing_rect_height="250dp"
app:zxing_framing_rect_width="250dp" />
<com.journeyapps.barcodescanner.ViewfinderView
android:id="#+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_possible_result_points="#color/zxing_custom_possible_result_points"
app:zxing_result_view="#color/zxing_custom_result_view"
app:zxing_viewfinder_laser="#color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_laser_visibility="true"
app:zxing_viewfinder_mask="#color/zxing_custom_viewfinder_mask" />
<TextView
android:id="#+id/zxing_status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="#color/zxing_transparent"
android:text="Place a QR code inside the scan area."
android:textColor="#color/zxing_status_text" />
</merge>
ScanQRActivity.java
public class ScanQRActivity extends AppCompatActivity implements DecoratedBarcodeView.TorchListener {
public static final String TAG = ScanQRActivity.class.getSimpleName();
Context mContext;
Activity mActivity;
ActivityScanQrBinding binding;
ActionBar actionBar;
private CaptureManager capture;
boolean bFlashLight = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityScanQrBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mContext = this;
mActivity = this;
capture = new CaptureManager(this, binding.zxingBarcodeScanner);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.setShowMissingCameraPermissionDialog(true);
capture.decode();
changeLaserVisibility(true);
}
public void changeLaserVisibility(boolean visible) {
binding.zxingViewfinderView.setLaserVisibility(visible);
}
}
To use data binding you need to place your layout inside tag.
Your activity.xml
<layout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/ll_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_below="#+id/ll_header"
android:background="#color/color_white"
android:gravity="center"
android:orientation="vertical">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="#+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_scanner_layout="#layout/view_custom_qr_scanner"/>
</LinearLayout>
</layout>
Your view_custom_qr_scanner.xml file should be
<layout>
<merge 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">
<com.journeyapps.barcodescanner.BarcodeView
android:id="#+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_framing_rect_height="250dp"
app:zxing_framing_rect_width="250dp" />
<com.journeyapps.barcodescanner.ViewfinderView
android:id="#+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_possible_result_points="#color/zxing_custom_possible_result_points"
app:zxing_result_view="#color/zxing_custom_result_view"
app:zxing_viewfinder_laser="#color/zxing_custom_viewfinder_laser"
app:zxing_viewfinder_laser_visibility="true"
app:zxing_viewfinder_mask="#color/zxing_custom_viewfinder_mask" />
<TextView
android:id="#+id/zxing_status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="#color/zxing_transparent"
android:text="Place a QR code inside the scan area."
android:textColor="#color/zxing_status_text" />
</merge>
</layout>
In your activity, create a new variable of type 'binding' that would be
private ViewCustomQrScannerBinding bindingCustomScanner
, now in your "OnCreate" under "binding = ActivityScanQrBinding.inflate (getLayoutInflater ());"
add this line
bindingCustomScanner = ViewCustomQrScannerBinding.bind (binding.root)
now when you call the properties of the new view, you call the new 'bindingCustomScanner'
I get this error from Android Studio even if I:
copied from an existent (and working) project, with any errors
changed package name in new project
This is the xml:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" alias="v"/>
<variable
name="viewModel"
type="....MyModel"/>
</data>
<android.support.v4.widget.NestedScrollView
android:id="#+id/fragment_question"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical">
<TextView
style="#style/QText.Big"
android:id="#+id/service_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Service name"
android:text="#{viewModel.serviceName}"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:visibility="#{viewModel.isDateType ? v.VISIBLE : v.GONE}">
<TextView
style="#style/QText.Big"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Date:"/>
<TextView
style="#style/Text.DateTime"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:drawableEnd="#drawable/date_icon"
android:text="#{viewModel.dateAnswer}"
android:onClick="#{viewModel.pickDate}"/>
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</layout>
This is my view model:
public class QuestionViewModel extends AbsQuestionViewModel {
public final ObservableString dateAnswer = new ObservableString();
private FragmentQuestionBinding binding;
public QuestionViewModel(Context context, FragmentQuestionBinding binding) {
super(context);
}
public boolean isLabelType() {
return answerType != null && (answerType.equals(ANS_TYPE_LABEL) || answerType.equals(ANS_TYPE_GEOPHOTO));
}
public boolean isDateType() {
return answerType != null && (answerType.equals(ANS_TYPE_DATE) || answerType.equals(ANS_TYPE_DATETIME));
}
public void pickDate(View v) {
DateTime.pickDate(context, dateAnswer::set);
}
}
What I dont understand is that I get the error just for pickDate attribute. I do not get the error for example for serviceName or dateAnswer attributes.
I tried to clean and rebuild the project and to invalidates cache and restart.
This is the exact error I get:
****/ data binding error ****msg:Could not resolve ...MyModel.pickDate as an accessor or listener on the attribute. file:/.../app/src/main/res/layout/fragment_q.xml loc:90:43 - 90:60 ****\ data binding error ****
The existing code has error on adding on click listener in xml using databinding
change
android:onClick="#{viewModel.pickDate}"
To
android:onClick="#{(v)-> viewModel.pickDate(v)}"
The Error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.databinding.ViewDataBinding.executePendingBindings()' on a null object reference
I double checked the names to the references used. Seems fine to me. I don't know why I keep getting this error. The view crashes as soon as I open it.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_findfriend);
searcher = Searcher.create(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY, ALGOLIA_INDEX_NAME);
helper = new InstantSearch(this, searcher);
helper.search();
// Get a reference to your Hits widget
final Hits hits = (Hits) findViewById(R.id.hits);
// Add an OnItemClickListener
hits.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
#Override
public void onItemClick(RecyclerView recyclerView, int position, View v) {
JSONObject hit = hits.get(position);
// Do something with the hit
}
});
}
#Override
protected void onDestroy() {
searcher.destroy();
super.onDestroy();
}
}
Here's my Activity:
activity_findfriend.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:algolia="http://schemas.android.com/apk/res-auto"
android:paddingTop="0dp"
android:background="#color/white">
<LinearLayout
android:id="#+id/search_emoji"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:background="#drawable/search_drawable"
android:gravity="top"
android:paddingTop="8dp"
android:orientation="horizontal">
<com.algolia.instantsearch.ui.views.SearchBox
android:id="#+id/searchBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/message_rectangle"
android:layout_marginRight="12dp"
android:layout_marginLeft="12dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/search_emoji">
<com.algolia.instantsearch.ui.views.Hits
android:id="#+id/hits"
android:layout_width="match_parent"
android:layout_height="wrap_content"
algolia:itemLayout="#layout/hits_item"
android:layout_below="#+id/search_emoji"/>
</LinearLayout>
To use data binding in your layout, wrap it in a <layout> root tag.
New hits_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:algolia="http://schemas.android.com/apk/res-auto">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:id="#+id/hits_items">
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/user_image"
android:layout_width="100dp"
android:layout_height="100dp"
app:civ_border_width="4dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:src="#drawable/profile_thumbnail"
app:civ_border_color="#c42f92"
algolia:attribute='#{"image"}'/>
<TextView
android:id="#+id/user_name"
android:paddingTop="53dp"
android:paddingLeft="20dp"
android:textSize="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
algolia:attribute='#{"username"}'
algolia:highlighted='#{true}'/>
</LinearLayout>
</layout>
I have 2 EditText views in my app:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#color/white">
<MyProject.MyView
android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="60dp" />
<EditText
android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/black"
style="#style/my_style"
android:hint="my hint2"/>
Here is the code for MyProject.MyView
public class MyView : LinearLayout
{
// not important code...
public LinearLayout Panel { get; private set; }
// Gets called from the constructor:
private void Init()
{
var layoutInflater = (LayoutInflater)this.Context.GetSystemService(Android.Content.Context.LayoutInflaterService);
this.content = layoutInflater.Inflate(Resource.Layout.my_content, this.Panel, true);
this.AddView(this.content);
}
}
And here is my_content:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
style="#style/my_style2">
<EditText
android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/my_style"
android:hint="my hint">
</EditText>
</LinearLayout>
The first EditText (that's being inflated from my MyView class) won't match the parent's width, it will only wrap the content. But the second EditText matches the parent's width. Why?
I solved it by wrapping the <LinearLayout> with a <RelativeLayout> in my my_content xml. I'm not sure why this was needed, so I would still appreciate an explanation so that I can better understand the way Android works.