I am using MVVM architecture in my app and there are 4 radiobuttons in a 2*2 grid inside a radiogroup but the the problem is oncheckedChanged is not getting called in viewmodel class, here's the xml code:
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_10sdp"
android:checkedButton="#id/singleRadioBtn"
android:onCheckedChanged="#{viweModel::selectOption}"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="0dp"
android:layout_height="#dimen/_30sdp"
android:layout_weight="1"
></RadioButton>
<Space
android:layout_width="#dimen/_8sdp"
android:layout_height="match_parent" />
<RadioButton
android:layout_width="0dp"
android:layout_height="#dimen/_30sdp"
android:layout_weight="1"
></RadioButton>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_8sdp"
android:orientation="horizontal">
<RadioButton
android:layout_width="0dp"
android:layout_height="#dimen/_30sdp"
android:layout_weight="1"
></RadioButton>
<Space
android:layout_width="#dimen/_8sdp"
android:layout_height="match_parent" />
<RadioButton
android:layout_width="0dp"
android:layout_height="#dimen/_30sdp"
android:layout_weight="1"
></RadioButton>
</LinearLayout>
</RadioGroup>
and in viewmodel:
fun selectOption(radioGroup: RadioGroup, id: Int)
{
radioGroup.check(id)
}
But the above function is not getting called. So what I am doing wrong here? Please help!
I think your problem is not with DataBinding - it's rather because you put LinearLayouts inside RadioGroup. Since Radiogroup is a subclass of LinearLayout itself it makes a mess, so in general you'll have to do something additional in code to make it work (but then DataBinding in the case is not so useful), you can look through discussion here.
If you try to place RadioButtons just inside RadioGroup (without nested LinearLayouts) I guess your method should be called.
As a workaround you could bind another callback - each RadioButton's onClick (setting index of RadioGroup there explicitly):
//...........
<RadioButton
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:onClick="#{(v) -> viewModel.selectOption(1)}"
></RadioButton>
<Space
android:layout_width="8dp"
android:layout_height="match_parent" />
<RadioButton
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:onClick="#{(v) -> viewModel.selectOption(2)}"
></RadioButton>
//...............
UPDATE
One of the choices - to make it work according to your current model:
To give id to Radiogroup (so it can be used in binding expression)
To give ids to RadioButtons
To change a little bit method in ViewModel
XML
<RadioGroup
android:layout_width="match_parent"
android:id="#+id/radioGroup"
.......>
<RadioButton
android:layout_width="0dp"
android:id="#+id/button1"
android:onClick="#{(v) -> viewModel.selectOption(radioGroup,v)}" // <- v - is your button
ViewModel
fun selectOption(radioGroup: RadioGroup, radioButton: View)
{
radioGroup.check(radioButton.id)
}
Related
I have a custom designed button (LinearLayout) that I want to reuse multiple times by just replacing a couple of attributes of the layout's nested views (icon and text).
I understand that using the <include> tag I can only override root view attributes.
I can sure do it programatically in java, but I wonder if there is a smart way to do this in XML.
Essentially, I want to be able to use something like <include> to reuse below shown complex layout and override only the following two nested attributes in two different nested views:
...
android:src="#drawable/google_icon"
...
android:text=" Google"
...
My (not yet) reusable layout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_vertical_margin"
android:layout_marginBottom="#dimen/button_vertical_margin"
android:gravity="center_horizontal"
android:clickable="true"
android:background="#drawable/default_button_selector">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="-2dp"
android:background="#drawable/layout_border"
android:gravity="center">
<ImageView
android:layout_width="#dimen/button_icon_size"
android:layout_height="#dimen/button_icon_size"
android:layout_margin="#dimen/button_icon_margin"
android:src="#drawable/google_icon" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/layout_border"
android:gravity="center"
android:paddingLeft="#dimen/button_text_horizontal_padding"
android:paddingRight="#dimen/button_text_horizontal_padding">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_text_vertical_margin"
android:layout_marginBottom="#dimen/button_text_vertical_margin"
android:textSize="#dimen/button_text_size"
android:text="Continue with" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_text_vertical_margin"
android:layout_marginBottom="#dimen/button_text_vertical_margin"
android:text=" Google"
android:textSize="#dimen/button_text_size"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
I am building an app that is in the Persian(Farsi) language, and of course, I need snackBar
but the problem is here:
Please take look at this photo, I want to set the Title on the right side of the snackBar
Here is my snackBar Code:
Snackbar.make(
mEditFragmentBiding.root,
resources.getText(R.string.empty_user_field_error),
Snackbar.LENGTH_LONG
)
.setAction(resources.getText(R.string.submit)) {
}
.setActionTextColor(resources.getColor(android.R.color.white))
.show()
Actually, I have visited and checked other answers like this or this one but there weren't what I wanted.
Appreciate any help.
Here is the link to the tutorial that those people whose language is Persian(right to left)need.
and if you want not to change the posion of some objects like TextViews you have to add this line in Xml of your object or layout.
android:layoutDirection="ltr"
android:gravity="right"
for instense:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layoutDirection="ltr"
android:gravity="right"
android:onClick="#{() -> viewModel.goToIncrease()}"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
android:gravity="center"
android:textColor="#color/black"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
android:gravity="center"
android:text="#string/submit_increase"
android:textColor="#color/black"
android:textSize="20sp" />
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="left"
android:src="#drawable/ic_baseline_add_circle_24" />
</LinearLayout>
just look at linear layout and you will figher out how to use(I said it for BEGINERES).
I started to develop for Android few days ago and I got stuck trying to use Radio Group. In my code for some reason all of the radio buttons can be selected together.
Any suggestion?
xml:
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/rG">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="89dp"
android:layout_below="#id/title"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="95"
android:layout_marginLeft="75sp"
android:layout_marginTop="20sp"
android:id="#+id/rb95"
android:layout_gravity="left|top"
android:checked="true"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="98"
android:id="#+id/rb98"
android:layout_gravity="right|top"
android:layout_alignTop="#+id/rb95"
android:layout_alignLeft="#+id/rbs"
android:layout_alignStart="#+id/rbs"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="96"
android:id="#+id/rb96"
android:layout_gravity="left"
android:layout_below="#id/rb95"
android:layout_alignLeft="#id/rb95"
android:layout_alignStart="#id/rb95"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="soler"
android:id="#+id/rbs"
android:layout_gravity="right"
android:layout_marginRight="75dp"
android:layout_alignTop="#id/rb96"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
</RadioGroup>
Pull the RadioButtons out of the RelativeLayout (get completely rid of it: it's not only misplaced, but also useless) and they will work as expected.
If you really need the RelativeLayout as a container for the RadioGroup, then swap the RelativeLayout and RadioGroup (RelativeLayout on the outside)
I think your problem is that you have a relativeLayout inside your RadioGroup.
Here is the Google Developer page on radio buttons.
I am trying to access a button from a specific view. The same view is displayed 6 times. This is the code I am using.
public void testTimeConfig(){
onData(withDesc("description")).onChildView(withId(R.id.positive)).perform(click());
}
private static Matcher<Object> withDesc(String desc) {
return allOf(is(instanceOf(String.class)), is(desc));
}
When I run, I get an error:
Error performing 'load adapter data' on view 'is assignable from class: class android.widget.AdapterView'.
Is this the best way to access a child view? If so, how?
EDIT
This is the code I am trying to use now.
onView(allOf((withContentDescription("description")), hasSibling(withContentDescription("SettingsLayout")), hasSibling(withId(R.id.positive)))).perform(click());
and
onView(allOf((withContentDescription("description")), hasSibling(withId(R.id.positive)))).perform(click());
With this Error:
No views in hierarchy found matching
The xml
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/setAGoalTitle"
android:layout_alignParentLeft="true"
class="com.xxx"
android:layout_marginTop="30dp"
android:id="#+id/timeGoalWidget"
app:goalLabel="#string/time_min_upper"
app:icon="#drawable/ic_icn_summary_time"
app:step="300"
app:valueFormat="time"
android:gravity="center_horizontal"
android:layout_marginBottom="60dp"
android:contentDescription="setAGoalTimeConfigurator"/>
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="#id/timeGoalWidget"
class="com.xxx"
android:id="#+id/distanceGoalWidget"
app:goalLabel="#string/distance_upper"
app:icon="#drawable/ic_icn_summary_track"
app:step="0.25"
app:valueFormat="decimal_two"
android:gravity="center_horizontal"
android:contentDescription="setAGoalDistanceConfigurator"/>
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/timeGoalWidget"
android:layout_alignLeft="#id/timeGoalWidget"
class="com.xxx"
android:id="#+id/paceGoalWidget"
app:goalLabel="#string/pace_upper"
app:icon="#drawable/ic_icn_summary_pace"
app:valueFormat="time"
app:step="10"
android:gravity="center_horizontal"
android:layout_marginBottom="60dp"
android:contentDescription="setAGoalPaceConfigurator"/>
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="#id/distanceGoalWidget"
android:layout_alignTop="#id/paceGoalWidget"
class="com.xxx"
android:id="#+id/speedGoalWidget"
app:goalLabel="#string/speed_upper"
app:icon="#drawable/ic_icn_summary_speed"
app:step="0.5"
app:valueFormat="decimal_two"
android:gravity="center_horizontal"
android:contentDescription="setAGoalSpeedConfigurator"/>
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/paceGoalWidget"
android:layout_alignLeft="#id/paceGoalWidget"
class="com.xxx"
android:id="#+id/inclineGoalWidget"
app:goalLabel="#string/incline_percent_upper"
app:icon="#drawable/ic_icn_summary_elevation"
app:step="0.5"
app:valueFormat="decimal_two"
android:gravity="center_horizontal"
android:contentDescription="setAGoalInclineConfigurator"/>
<view
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="#id/speedGoalWidget"
android:layout_alignTop="#id/inclineGoalWidget"
class="com.xxx"
android:id="#+id/caloriesGoalWidget"
app:goalLabel="#string/calories_upper"
app:icon="#drawable/ic_icn_summary_calories"
app:step="10"
app:valueFormat="decimal_zero"
android:gravity="center_horizontal"
android:contentDescription="setAGoalCaloriesConfigurator"/>
</RelativeLayout>
The view xml that is used 6 times.
<ImageButton
android:id="#+id/increaseGoalButton"
android:layout_height="#dimen/view_goal_setting_incrementor_button_height_width"
android:layout_width="#dimen/view_goal_setting_incrementor_button_height_width"
android:background="#drawable/button_goal_widget"
android:gravity="center"
android:src="#drawable/ic_plus"
android:textSize="#dimen/view_goal_setting_incrementor_button_text_size"
android:textColor="#color/goal_configuration_widget_button_text_color"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="1dp"
android:contentDescription="#string/increase"/>
<ImageButton
android:id="#+id/decreaseGoalButton"
android:layout_height="#dimen/view_goal_setting_incrementor_button_height_width"
android:layout_width="#dimen/view_goal_setting_incrementor_button_height_width"
android:background="#drawable/button_goal_widget"
android:gravity="center"
android:src="#drawable/ic_minus"
android:textSize="#dimen/view_goal_setting_incrementor_button_text_size"
android:layout_alignParentRight="true"
android:textColor="#color/goal_configuration_widget_button_text_color"
android:layout_below="#id/increaseGoalButton"
android:contentDescription="#string/decrease"/>
<LinearLayout
android:id="#+id/goalWidgetValueContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toLeftOf="#id/increaseGoalButton"
android:layout_centerVertical="true"
android:gravity="center_vertical|right"
android:layout_marginRight="#dimen/view_goal_setting_value_margin_right" >
<TextView
android:id="#+id/goalValueTextView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="#color/goal_configuration_widget_value_text_color"
android:textSize="#dimen/view_goal_setting_value_text_size"
android:lineSpacingExtra="-10sp"
app:typeface="proxima_bold"
android:text="999:00"/>
<TextView
android:id="#+id/goalValueLabelTextView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:textSize="#dimen/view_goal_setting_value_label_text_size"
android:textColor="#color/goal_configuration_widget_value_text_color"
android:includeFontPadding="false"
android:lineSpacingExtra="10sp"
android:text="#string/incline_percent_upper"/>
</LinearLayout>
It is the ImageView with id increaseGoalButton that I am trying to click.
Based on your last comment you should use onView() instead of onData().
I think you'll be able to click the button using hasSibling() - example
onView(allOf(withId(R.id.positive), hasSibling(withDesc(someString))))
.perform(click());
or examples without your custom matcher (sibling view has text):
onView(allOf(withId(R.id.positive), hasSibling(withText(someString))))
.perform(click());
or (sibling view has content description):
onView(allOf(withId(R.id.positive), hasSibling(withContentDescription(someString))))
.perform(click());
EDITED:
OK, I'd try these two variants:
onView(allOf(withId(R.id.increaseGoalButton), isDescendantOfA(withId(R.id.timeGoalWidget))))
.perform(click());
or
onView(allOf(withId(R.id.increaseGoalButton), withParent(withId(R.id.timeGoalWidget))))
.perform(click());
None of your content descriptions match the string "description" that's why it doesn't find anything.
Assuming the button id is R.id.positive, and the id is unique in the current activity view, you can simply use:
onView(withId(R.id.positive)).perform(click());
So I have the following radiobuttons. I want to have them display like this:
However this occurs:
How I can get it to display like above? I can move in the GUI editor in Eclipse it but it removes the RadioButton from the RadioGroup!Within the group, it ignores all other layout parameters.
<RadioGroup
android:id="#+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/timeBar"
android:layout_marginTop="43dp"
android:orientation="horizontal" >
<RadioButton
android:id="#+id/privRadio0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Everyone" />
<RadioButton
android:id="#+id/privRadio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="FriendOfFriends" />
<RadioButton
android:id="#+id/privRadio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Friends" />
</RadioGroup>
You can simply copy this class:
https://github.com/jevonbeck/AbstractMachine/blob/jevon_dev/app/src/main/java/org/ricts/abstractmachine/ui/utils/MultiLineRadioGroup.java
into an appropriate package in your project and instantiate in XML like so:
<view
class="mypackage.packagepath.MultiLineRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
What you are asking for is a FlowLayout. Such a layout has the benefit of only wrapping when it's needed, as opposed to 0gravity's more "static" solution.