How to define a custom BindingMethod for a TextView? - android

I am starting to work with the new data binding API. I want to bind on a TextView a custom property where I change the text and background at once. As far I understood the api there is a #BindingMethod annotation for this, but the documentation is there a little weak.
I want something like this:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Important"
tools:background="#drawable/bg_badge_important"
tools:textColor="#fff"
android:id="#+id/badge"
custom:badge="#{item.badge}"/>
Where this item.badge is a string like important or notice. For i18n I cannot use this string directly but this will help me to choose the right text and the right background image.
Can you give me a small example or a reference how to use this attribute? I just found one answer on Stack Overflow, but this does not answer my question.

Just create a public static method on your codebase and annotate with #BindingAdapter.
Here is an example for fonts:
https://plus.google.com/+LisaWrayZeitouni/posts/LTr5tX5M9mb
Edit by rekire I ended in using this code:
#BindingAdapter({"bind:badge"})
public static void setBadge(TextView textView, String value) {
switch(value) {
case "email":
textView.setText(R.string.badge_email);
textView.setBackgroundResource(R.drawable.bg_badge_email);
break;
// other cases
}
}

Related

Android BindAdapter with custom attribute with custom values (similar to visible attribute)

I've successfully made my first bind adapter and I wish to know a bit more about it.
I want to know how to make an attribute that can get only specific strings for a different state for my view.
For example every view has the visibility attribute that it can be"gone", "visible", "invisible"
<TextView
android:id="#+id/loading_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="#id/inventory_items_recycler"
app:layout_constraintEnd_toEndOf="#+id/inventory_items_recycler"
app:layout_constraintStart_toStartOf="#id/inventory_items_recycler"
app:layout_constraintBottom_toBottomOf="#id/inventory_items_recycler"
android:textSize="18sp"
android:visibility="gone"
app:item_id="#{ItemID.BLACK_GLOVES.ordinal()}"
/>
I've made a custom attribute called item_id that get a number that represent enum value. And in my binding utils I have this code:
#BindingAdapter("item_id")
public static void setItemName(TextView tv, int itemId) {
tv.setText(ItemData.get(ItemID.values()[itemId]).getName());
}
I prefer to have something similar to the visibility attribute that it value can be either "visible", "invisible" or "gone"
Bonus::
I wish android studio can auto-complete me for the possibilities that I can use.
You could pass directly the enum to your binding adapter, instead of converting it first to an int and than back to enum.
#BindingAdapter("item_id")
public static void setItemName(TextView tv, ItemID itemId) {
..
}
Then you could pass directly the enum in your xml:
app:item_id="#{ItemID.BLACK_GLOVES}"
This way you'll have a limited number of possibilities to enter and will be less likely to accidentally enter a meaningless integer.
However, binding adapters and custom attibutes are different. With a binding adapter, you still need to use the syntax of binding expression, ie: "#{ }".
android:visibility , on the other hand, is an attribute. You can also define custom attributes for your custom views and get something similar (have a limited number of input options and IDE shows you your options etc). But you shouldn't confuse that with binding adapters. These are two different concepts.
Try this:
#BindingAdapter("isGone")
#JvmStatic
fun View.setVisibility(isGone: Boolean) {
if (isGone) this.visibility = View.GONE else View.VISIBLE
}
Inside your xml:
<com.google.android.material.checkbox.MaterialCheckBox
android:id="#+id/cb_class"
style="#style/TextStyleNormal.White"
android:layout_marginStart="#dimen/margin_large"
isGone="#{isSharedDailyActivity}"// it take boolean value
app:buttonTint="#color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:useMaterialThemeColors="true" />

How to display several paragraphs of text in android studio

In the app I'm building, I'm hoping to have several different guides / tutorials that will each contain several paragraphs and hopefully pictures in them. Right now the only thing I would know to do is to have all of the different texts written out long form in my strings resource file. I would then need to have separate layouts and fragments for each tutorial.
Is there an easier way? Can I separate my strings resource file at least so that I don't have that one file completely bogged down? Could I maybe import the text from a separate file?
Yes, you can. you need to set text programmatically. You need only one layout for all of these same type information page.
Let's say you have
<TextView
android:id="#+id/text_view_id"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="#string/hello" />
You can get that text view from java activity like below and set the text you want..
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView helloTextView = (TextView) findViewById(R.id.text_view_id);
helloTextView.setText(R.string.user_greeting);
}
}
you can do this setText process by adding a switch, if or any conditional checking process like below
switch(expression) {
case value :
helloTextView.setText(R.string.firstPageText);
break;
case value :
helloTextView.setText(R.string.secondPageText);
break; // optional
// You can have any number of case statements.
helloTextView.setText(R.string.defaultText);
// Statements
}
PS: I think you can use different text style while you creating resource text. You can follow this https://www.myandroidsolutions.com/2017/09/29/android-html-textview/#.W9pu1mgzaUk for it.

Is there an XML equivalent to HTML classes?

Sorry if this is a really obvious question, but I've been trying to find something like it in a number of places, and I'm not sure if it just doesn't exist or if I'm using the wrong language to describe what I need.
If, for example, I have a number of TextViews in different parts of my activity, and I want all of them to open the same activity when clicked on, how would I do this without specifying each of their IDs individually in an if statement in the Java? In HTML I would use a class attribute to group them together, but I can't find a similar feature in XML.
Thanks for your help!
If your intention is to prevent code repetition and tedious code repetition, then one way is to use ButterKnife. Something link below would work:
#OnClick({R.id.view_id1, R.id.view_id2, R.id.view_id3})
public void onClick(View view) {
// TODO: Handle click
}
Or, as the other answer suggests, you can have android:onClick attribute on each of those views which points to same method in Java code.
Write your xml code of EditText as follows
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Fourth EditText"
android:onClick="editTextClick"/>
And in Java file write method
public void editTextClick(View v) {
// does something very interesting
Log.d("MainActivity","EditText pressed");
}
I hope this will help you,
Happy Coding

How to override a button attribute

I should be able to use a #BindingAdapter in Android dataBinding so that i can override a certain attribute. I am able to do it with a cusutom attribute but with a android built-in attribute how is it accomplished?
what i have so far:
in my viewModel i have a method that is annotated with #BindingAdapter and looks like this:
#BindingAdapter({"android:text"})
public static void setText(Button view,boolean language) {//i need to pass one more variable in here for area code , its just a integer, but how ?
if("french".equals(language))//i want to test if french && area code
view.setText("si vous play");
else if ("English".equals(language)) //i want to test if french && area code
view.setText("please");
}
but i have a few problems. Lets see the xml :
<Button
android:id="#+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{`french,844`}"/>
See my issue, i want to pass in more then one parameter to dataBinding. But how ? Do i have to make a POJO object and pass it in ? even if i did that how do i set the object from xml ?
So if someone can just tell me the following i'll be fine:
1. how to pass multiple values to a bindingAdapter and
2. How to override a built-in android attribute in any view.
If you want to set two different values in your BindingAdapter, you should use two different attributes:
<Button
android:id="#+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{`french`}"
app:areaCode="#{`844`}"/>
Then have two different attributes in your BindingAdapter:
#BindingAdapter({"android:text", "areaCode"})
public static void setText(Button view, String language, String areaCode) {
...
}
But it would probably be better to set a different "app:language" as that would be more clear to the developer.

include tag in xml file of Android Programming

I have a question regarding the tag. Actually I am new to the Android Programming and I want to use the Concept of Reusability in my Application at several places. I get to know that it is possible by the tag but I don't know how to use that. I have refered some of it's examples from the net but didn't found them quite satisfactory.
Can anybody please make me understand it with a Clear and appearant example!
Thanks
john
Let's say on an activity you have several buttons, all almost doing similar stuff onClick. Now you can use an onClick method, but since you cannot pass parameters in the onClick attribute, you need to put it somewhere else, which is where tag comes in handy.
In your layout you might have:
<Button android:id="#+id/btn1"
android:tag="paramValue1"
android:onClick="myOnClick"/>
<Button android:id="#+id/btn2"
android:tag="paramValue2"
android:onClick="myOnClick"/>
Then you can use one central custom onClickListener (especially if you want to reuse amonst multiple activities) or like in my case just a method in my activity for your buttons that handle the actions for it.
public void myOnClick(View v) {
String param = (String) v.getTag();
....
}
This is especially useful for generic actions, and also if you want to reuse code (i.e. same button listener) amongst multiple classes/activities.
This way you don't rely on a switch/case and checking your button (view) id; staying more independent from your activity itself.

Categories

Resources