How can I force a MaterialButtonToggleGroup to act like a RadioGroup as in having at least one selected item always? Setting setSingleSelection(true) also adds the possibility to have nothing selected if you click twice on a Button in the group.
Here is my code:
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="#id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true"
app:checkedButton="#+id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Ascending">
<com.google.android.material.button.MaterialButton
android:id="#id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Ascending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Fragment_BottomSheetDialog_Sort_ToggleButton_Ascending"
app:backgroundTint="#color/custom_button_background_states"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"/>
<com.google.android.material.button.MaterialButton
android:id="#id/BottomSheetDialog_fromFragmentBottomSheetSort_Sort_ToggleButtonGroup_Descending"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/Fragment_BottomSheetDialog_Sort_ToggleButton_Descending"
app:backgroundTint="#color/custom_button_background_states"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"/>
</com.google.android.material.button.MaterialButtonToggleGroup>
As you can see, even while using app:singleSelection="true" if i click on an already checked button, it unchecks it leaving no button checked in the group.
UPDATE :
app:selectionRequired="true" attribute is available as of version 1.2.0
Override the toggle() method of the MaterialButton class and use it instead of MaterialButton
import android.content.Context
import android.util.AttributeSet
import com.google.android.material.button.MaterialButton
class CustomMaterialToggleButton : MaterialButton {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun toggle() {
if (!isChecked) {
super.toggle()
}
}
}
This will make sure that already checked button is not unchecked on single selection.
As of 1.2.0-alpha03 you can simply use the selectionRequired option:
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="#+id/toggle_button_group"
app:singleSelection="true"
app:selectionRequired="true">
</com.google.android.material.button.MaterialButtonToggleGroup>
Now you can achieve it using the app:selectionRequired attribute.
Something like:
<com.google.android.material.button.MaterialButtonToggleGroup
app:singleSelection="true"
app:selectionRequired="true"
app:checkedButton="#id/..."
..>
Also you can programmatically use the method setSelectionRequired:
buttonGroup.setSelectionRequired(true);
Please note that this attribute requires a minimum of version 1.2.0-alpha03
If you really want to do this, you can go about it this way in Kotlin.
toggle_group.forEach { button ->
button.setOnClickListener { (button as MaterialButton).isChecked = true }
}
This will prevent second click unchecking.
Related
Using:
com.google.android.material:material:1.4.0
If I have a layout xml file in a fragment/activity with a TextView:
<TextView
style="#style/TextAppearance.MaterialComponents.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
If I go between light/dark mode the text color switches appropriately.
However if I create a custom view:
class MyView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyle, defStyleRes) { ... }
And that view contains the same textview, the text color does not change in night mode.
I initialize the view from a fragment:
new MyView(this.getActivity().getBaseContext());
I have also tried to directly apply the base theme:
new MyView(this.getActivity().getBaseContext(), null, R.id.AppTheme);
In addition for some strange reason I can work around this issue by creating my own text colors in the appropriate light/dark folders and that picks up the change between light/dark:
<TextView
style="#style/TextAppearance.MaterialComponents.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/my_text_color" />
Turns out I was passing the wrong context.
When creating the view:
new MyView(this.getActivity().getBaseContext());
Should be:
new MyView(this.getActivity());
How can I make last visible items of recycler view to have a slight different style. For example, I would like them to appear like this:
As you can see, the last 3 items are grayed out proportionally. I have searched the internet but no success. Any suggestions would be greatly appreciated!
Find out the size of the list you are using to populate the recyler view, this may have been set in the adapter constructor. I'll call it myList.
then in your onBindViewHolder something like:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
....
if (myList.size() - position < 3) {
holder.wordRow.setTextColor(this.mContext.getResources().getColor(R.color.light_gray));
}
Where wordRow is a TextView element
You can create a custom recyclerView layout and then set the topFadingEdgeLength to 0.0. This will allow you to only give effect in the bottom, else it will be applied to the top also.
In your XML
<com.example.BottomFadeEdgeRecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadingEdge="vertical"
android:fadingEdgeLength="180dp"
android:requiresFadingEdge="vertical">
</com.example.BottomFadeEdgeRecyclerView>
I have set the fadingEdgeLength to 180dp. You can set the desired value
And the custom view class
import android.content.Context
import android.util.AttributeSet
import androidx.recyclerview.widget.RecyclerView
class BottomFadeEdgeRecyclerView : RecyclerView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun getTopFadingEdgeStrength(): Float {
return 0.0f
}
}
you can create a custom scrollView layout and then set the topFadingEdgeLength to 0.0. This will allow you to only give effect in the bottom, else it will be applied to the top also.
You can use the scrollView to wrap your recyclerView
In the XML set your scrollView as below
<com.example.BottomFadeEdgeScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadingEdge="vertical"
android:fadingEdgeLength="180dp"
android:requiresFadingEdge="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.example.BottomFadeEdgeScrollView>
I have set the fadingEdgeLength to 180dp. You can set the desired value
Here's the file in Kotlin
import android.content.Context
import android.util.AttributeSet
import android.widget.ScrollView
class BottomFadeEdgeScrollView : ScrollView {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun getTopFadingEdgeStrength(): Float {
return 0.0f
}
}
I need to make a multiline text material button.
I have followed this question's answers, but it turns out that material buttons work differently.
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="#+id/toggle_parent_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:theme="#style/Theme.MaterialComponents"
android:visibility="gone"
app:checkedButton="#id/button_parent"
app:singleSelection="true">
<com.google.android.material.button.MaterialButton
android:id="#+id/button_parent"
style="#style/Login.Button.ToggleButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Parent\n Device" />
<com.google.android.material.button.MaterialButton
android:id="#+id/button_child"
style="#style/Login.Button.ToggleButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Child \n Device" />
I'm getting this:
but I need every word to be in a different line like this:
It might be late but here is my implementation to fix it
class MonsterButtonToggleGroup : MaterialButtonToggleGroup {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
super.addView(child, index, params)
if (child is MaterialButton)
child.maxLines = 2
}
}
you can use replace to make it a multiline string in you MaterialButton like this -
val singleLine = getString(R.string.hello_blank_activity)
demoText.text = singleLine
val multiLine = singleLine.replace(" ", "\n")
demoTextMulti.text = multiLine
Here is the screenshot of the output -
I have Custom View called LoadingButton extending FrameLayout. This class is inflatin custom XML layout containing LinearLayout and ProgressBar with parent FrameLayout. This should be functional as Button. I have custom defined styles for each Button type (changing background, tint, text color ...). I want to pass this style into my Custom View class. But it doesnt work. This type of constructor is not called. Instead general construtor with Context and AttributeSet is called.
Any explanation? I though if I add style into my custom View it will be automatically detected and different type of constructor is called.
Constructors:
#SuppressLint("ClickableViewAccessibility")
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
parseAttrs(context, attrs)
}
#SuppressLint("ClickableViewAccessibility")
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
parseAttrs(context, attrs, defStyleAttr)
}
Usage of Custom View:
<com.project.custom.LoadingButton
android:id="#+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/button_blue_filled"
app:l_buttonText="#string/text"
android:layout_marginTop="48dp" />
Image Here
how i will set custom font my my android app option menu right size top of the screen. It should be custom font like Raleway Regular.
Create a class
public class Railway_Bold extends TextView {
public Railway_Bold(Context context, AttributeSet attrs) {
super(context, attrs);
this.setTypeface(Typeface.createFromAsset(context.getAssets(),"fonts/Raleway-Bold.ttf"));
}}
use this class to yout textview...
<your_package_name.fonts.Railway_SemiBold
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Trending Articles"
android:textColor="#color/black"
android:textSize="18dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"/>