View has extra pixels when rounding corners - android

I have some missunderstading why this is happening. I have a parent FrameLayout that has rounded corners, and a TextView with bottom rounded corners. Corner raduses are equal, but on the screen displaying some extra pixels.
I got the same behavior with default xml rounding, and i would like to receive right work of rounded corners with not affect of parent view.
Custom text View
class SampleTextView #JvmOverloads constructor(
context: Context,
attributeSet: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatTextView(context, attributeSet, defStyleAttr) {
private val cornerRadius: Float = 20f
init {
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val left = 0
val top = 0
val right = view.width
val bottom = view.height
outline.setRoundRect(
left,
(top - cornerRadius).toInt(),
right,
bottom,
cornerRadius
)
}
}
clipToOutline = true
}
}
Xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/fl"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.example.testproject.SampleTextView
android:id="#+id/child"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="bottom"
android:background="#color/black"
android:text="Some text text"
android:textColor="#color/white" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val parent = findViewById<FrameLayout>(R.id.fl)
parent.outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val left = 0
val top = 0
val right = view.width
val bottom = view.height
outline.setRoundRect(left, top, right, bottom, 20.toFloat())
}
}
parent.clipToOutline = true
}
}
Strange behavior

Related

Custom Button component: shadow is clipped

I have custom LoadingButton class implemented as FrameLayout which is then used inside XMLs as component. Its basically Button but made completely custom with its own layout and components.
What I want is to add shadow there (elevation, translationZ) but this shadow is clipped everywhere.
I want to have this button dynamic that I can adjust its margins or change its shape like adding static width and height on different screens without distorting shadow around. Shadow is clipped either from top or bottom all the time.
Example of xml view:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="CustomRes" type="com.project.utils.CustomResources"/>
</data>
<merge
android:duplicateParentState="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/buttonParent"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:duplicateParentState="true"
android:clipToPadding="false"
android:clipChildren="false"
android:gravity="center">
<ImageView
android:id="#+id/buttonIcon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:layout_gravity="center"
android:scaleType="fitCenter"/>
<TextView
android:id="#+id/buttonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:textSize="#dimen/text_medium"
android:textStyle="bold"
android:lines="1"
android:layout_gravity="center"/>
</LinearLayout>
<com.project.components.loading_indicator.LoadingIndicator
android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center" />
</merge>
</layout>
Class:
#Suppress("DEPRECATION")
class LoadingButton : FrameLayout {
#StyleableRes
internal val btnIcoIndex = 0
#SuppressLint("ResourceType")
#StyleableRes
internal val btnTextResIndex = 1
#StyleableRes
#SuppressLint("ResourceType")
internal val btnTextIndex = 2
#StyleableRes
#SuppressLint("ResourceType")
internal val btnTextSizeIndex = 3
private val buttonParent: LinearLayout
private val progressBar: LoadingIndicator
private val buttonIcon: ImageView
private val buttonText: TextView
private var buttonTextVal: String? = null
init {
CustomResources.inflateLayout(LayoutInflater.from(context), R.layout.loading_button, this)
buttonParent = findViewById(R.id.buttonParent)
buttonIcon = findViewById(R.id.buttonIcon)
buttonText = findViewById(R.id.buttonText)
progressBar = findViewById(R.id.progress)
buttonText.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
textViewInitWidth = maxOf(v.measuredWidth, textViewInitWidth)
}
}
#SuppressLint("ClickableViewAccessibility")
constructor(context: Context) : super(context) {
parseAttrs(context)
}
#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)
}
#SuppressLint("ResourceType")
private fun parseAttrs(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int? = null) {
//Load from custom attributes
setLoading(false)
val sets = intArrayOf(R.attr.l_buttonIcon, R.attr.l_buttonTextId, R.attr.l_buttonText, R.attr.l_buttonTextSize)
if (attrs != null){
val typedArray = context.obtainStyledAttributes(attrs, sets)
val buttonIco = typedArray.getResourceId(btnIcoIndex, 0)
val buttonTxtRes = typedArray.getText(btnTextResIndex)?.let { res->
App.getString(res as String).toLowerCase(Locale.getDefault()).replaceFirstChar { it.toUpperCase() }
}
val buttonTxtRaw = typedArray.getText(btnTextIndex)?.let { it as String }?:"null"
val buttonTxtSize = typedArray.getDimension(btnTextSizeIndex, resources.getDimension(R.dimen.text_medium))
val buttonStyle = attrs.styleAttribute
App.log("RawTextButton: $buttonTxtRaw, hasValue: ${typedArray.getString(btnTextIndex)}")
setButtonTextSize(buttonTxtSize)
buttonTxtRes?.let { setButtonText(buttonTxtRes) }?:kotlin.run{ setButtonText(buttonTxtRaw) }
setButtonIcon(buttonIco)
buttonParent.gravity = Gravity.CENTER
buttonTextVal = buttonTxtRes?.let { buttonTxtRes.toString() }?:buttonTxtRaw
typedArray.recycle()
clipToPadding = false
clipChildren = false
when(buttonStyle){
R.style.button_primary -> {
App.log("BtnStyleId - primary")
setupTextStyle(buttonStyle)
setProgBarColor(R.color.button_light)
setIconTint(ContextCompat.getColor(context, R.color.button_light))
maybeSetAmbientShadow(R.color.button_primary)
}
R.style.button_secondary -> {
App.log("BtnStyleId - secondary")
setupTextStyle(buttonStyle)
setProgBarColor(R.color.button_primary)
setIconTint(ContextCompat.getColor(context, R.color.button_light))
maybeSetAmbientShadow(R.color.button_primary)
}
R.style.button_secondary_alert -> {
App.log("BtnStyleId - secondary alert")
setupTextStyle(buttonStyle)
setProgBarColor(R.color.button_invalid)
setIconTint(ContextCompat.getColor(context, R.color.button_invalid))
maybeSetAmbientShadow(R.color.button_invalid)
}
else -> App.log("BtnStyleId -> $buttonStyle")
}
} else {
App.log("BtnStyleId -> attrs==null")
}
}
#SuppressLint("ResourceType")
private fun setupTextStyle(buttonStyle: Int){
val attrs = intArrayOf(android.R.attr.textAppearance)
val typedAttrs = context.obtainStyledAttributes(buttonStyle, attrs)
val textAppearance = typedAttrs.getResourceId(0, 0)
TextViewCompat.setTextAppearance(buttonText, textAppearance)
typedAttrs.recycle()
}
private fun setProgBarColor(color: Int){
progressBar.setColorTint(color)
}
fun setIconTint(color: Int){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
buttonIcon.colorFilter = BlendModeColorFilter(color, BlendMode.SRC_IN)
} else {
App.log("setting color filter")
buttonIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN)
}
}
private fun maybeSetAmbientShadow(color: Int){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
outlineAmbientShadowColor = ContextCompat.getColor(this.context, color)
outlineSpotShadowColor = ContextCompat.getColor(this.context, color)
}
}
}
I need some variable to set which will set clipToPadding false and clipChildren false for every single screen where this button is implemented without rewriting 80+ xml files. Because some screens have marginTop set for this button but not marginBottom, and that will cause clipping even if I set those 2 parameters to false. Clearly bad design from Android for handling shadows.
Base style for primary and secondary button:
<style name="button" parent="#android:style/Widget.Material.Button">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:minHeight">0dp</item>
<item name="android:minWidth">0dp</item>
<item name="android:paddingStart">#dimen/button_padding_start</item>
<item name="android:paddingEnd">#dimen/button_padding_end</item>
<item name="android:paddingTop">#dimen/button_padding_top</item>
<item name="android:paddingBottom">#dimen/button_padding_bottom</item>
<item name="android:elevation">4dp</item>
<item name="android:translationZ">4dp</item>
<item name="android:stateListAnimator">#null</item>
<item name="android:clipToPadding">false</item>
</style>
Usage:
<com.project.components.loading_button.LoadingButton
android:id="#+id/loginButton"
android:layout_gravity="center"
android:layout_weight="0.5"
android:layout_marginStart="8dp"
app:l_buttonTextId="button_login"
style="#style/button.primary" />

Material Cardview - rounded corner of TabLayout not getting clipped

When I'm putting my TabLayout inside MaterialCardView to make TabLayout rounder but I'm not getting desired result
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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 = "match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
app:cardCornerRadius="#dimen/dp_20"
android:theme="#style/Theme.MaterialComponents.Light"
app:strokeColor="#color/dark_blue"
app:cardPreventCornerOverlap="true"
app:strokeWidth="1dp">
<com.google.android.material.tabs.TabLayout
android:id = "#+id/tab_layout"
android:layout_width = "match_parent"
android:layout_height = "#dimen/dp_35"
app:tabGravity = "fill"
app:tabIndicatorColor = "#color/dark_blue"
app:tabIndicatorGravity = "stretch"
app:tabMaxWidth = "0dp"
app:tabMode = "fixed"
app:tabSelectedTextColor = "#android:color/white"
app:tabTextAppearance = "#style/AppTabTextTools"
app:tabTextColor = "?attr/colorPrimary">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Please help me to figure out what's the problem in above layout.
I need result like below image
As suggested by #Malik Saifullah followed https://stackoverflow.com/a/50621395/770703
Created custom RoundedTabLayout class for simplification
class RoundedTabLayout : TabLayout, TabLayout.OnTabSelectedListener {
private lateinit var currentContext: Context
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
currentContext = context
addOnTabSelectedListener(this)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
currentContext = context
addOnTabSelectedListener(this)
}
constructor(context: Context) : super(context)
override fun onTabSelected(tab: Tab?) {
if (selectedTabPosition == 0) {
setTabBG(R.drawable.tab_left_select, R.drawable.tab_right_unselect)
} else {
setTabBG(R.drawable.tab_left_unselect, R.drawable.tab_right_select)
}
}
override fun onTabUnselected(tab: Tab?) {
}
override fun onTabReselected(tab: Tab?) {
}
private fun setTabBG(tab1: Int, tab2: Int) {
val tabStrip = getChildAt(0) as ViewGroup
val tabView1 = tabStrip.getChildAt(0)
val tabView2 = tabStrip.getChildAt(1)
if (tabView1 != null) {
val paddingStart = tabView1.paddingStart
val paddingTop = tabView1.paddingTop
val paddingEnd = tabView1.paddingEnd
val paddingBottom = tabView1.paddingBottom
ViewCompat.setBackground(tabView1, AppCompatResources.getDrawable(tabView1.context, tab1))
ViewCompat.setPaddingRelative(tabView1, paddingStart, paddingTop, paddingEnd, paddingBottom)
}
if (tabView2 != null) {
val paddingStart = tabView2.paddingStart
val paddingTop = tabView2.paddingTop
val paddingEnd = tabView2.paddingEnd
val paddingBottom = tabView2.paddingBottom
ViewCompat.setBackground(tabView2, AppCompatResources.getDrawable(tabView2.context, tab2))
ViewCompat.setPaddingRelative(tabView2, paddingStart, paddingTop, paddingEnd, paddingBottom)
}
}
}

Custom TextView alignment

I wrote a small custom text view in order to use it on a list. There are three States depending on which i want to have this:
State 1 -> just the text, for example TEST_TEXT
State 2 -> a drawable start, a color background and the same text TEST_TEXT
State 3 -> a different drawable start, different color background and the same text TEST_TEXT
The text has always the same value (TEST_TEXT)
But with my implementation i lost the alignment and as a result the text on the state that
i do not have a drawable start is not align with the others that have drawable as you can see on the image below. I want all of them to be start align.
Is there a way to achieve it?
My custom text view class is :
enum class State {
STATE_ONE,
STATE_TWO,
STATE_THREE
}
class CustomTextView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
): TextView(context, attrs, defStyleAttr) {
private val PADDING = 4 * resources.displayMetrics.density
private val ZERO_PADDING = 0 * resources.displayMetrics.density
var state: State = State.STATE_ONE
set(value) {
field = value
updateTextView()
invalidate()
}
private fun updateTextView() {
when(state) {
State.STATE_TWO -> {
this.setBackgroundResource(R.color.light_red)
this.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_message_24, 0, 0, 0)
this.compoundDrawablePadding = PADDING.toInt()
this.setPadding(PADDING.toInt(), PADDING.toInt(), PADDING.toInt(), PADDING.toInt())
}
State.STATE_THREE -> {
this.setBackgroundResource(R.color.colorGreenBright)
this.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_baseline_message_24, 0, 0, 0)
this.compoundDrawablePadding = PADDING.toInt()
this.setPadding(PADDING.toInt(), PADDING.toInt(), PADDING.toInt(), PADDING.toInt())
}
else -> {
this.setBackgroundResource(R.color.transparent)
this.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
this.compoundDrawablePadding = PADDING.toInt()
this.setPadding(ZERO_PADDING.toInt(), ZERO_PADDING.toInt(), ZERO_PADDING.toInt(), ZERO_PADDING.toInt())
}
}
}
}
The layout where i add them is this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<custom.textView.CustomTextView
android:id="#+id/textViewOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST_TEXT"
android:textSize="12sp"
android:textColor="#color/black"
android:background="#drawable/drawable_rounded_text_bg"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="30dp"/>
<custom.textView.CustomTextView
android:id="#+id/textViewTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST_TEXT"
android:textSize="12sp"
android:textColor="#color/black"
android:background="#drawable/drawable_rounded_text_bg"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewOne"
android:layout_marginTop="10dp"/>
<custom.textView.CustomTextView
android:id="#+id/textViewThree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST_TEXT"
android:textSize="12sp"
android:textColor="#color/black"
android:background="#drawable/drawable_rounded_text_bg"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewTwo"
android:layout_marginTop="10dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
and finally my activity is simple like this:
class CustomTextActivity: BaseActivity() {
private lateinit var binding: ActivityCustomTextBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(getView())
initLayout()
}
override fun getView(): View {
binding = ActivityCustomTextBinding.inflate(layoutInflater)
return binding.root
}
private fun initLayout() {
binding.textViewOne.state = State.STATE_ONE
binding.textViewTwo.state = State.STATE_TWO
binding.textViewThree.state = State.STATE_THREE
}
}
To my mind, if you want to have the same alignment, even without inner drawables, you have 2 options:
right align the text
display a "fake drawable" in the first case

RecyclerView height gets wrapped after keyboard gets closed

I have a form which contains 2 fields and under those, few generated buttons in a RecyclerView. The RecyclerView has a GridLayout of 2 columns. My cells
I just noticed a bug which appears when I close the native keyboard (it has opened after I filled my two fields)
If I take the example of 3 buttons, I would have in my RecyclerView one row with 2 cells and a second row with one.
After closing my keyboard, the RecyclerView gets wrapped into one row of 2 cells and to access the second row, I have to scroll inside the RecyclerView.
I tried with a LinearLayout, same bug.
I tried few fixes found on StackOverFlow :
setting the keyboard to adjustPan in the Manifest
setting height to match_parent to my cells and layouts
None of those worked.
Here are some screens of the bugs:
Before opening the keyboard :
After closing the keyboard :
Any idea on how to fix this ?
Best regards
UPDATE 1 :
As asked, here are some code samples to reproduce the problem :
Adapter Setup :
binding.actionButtonsContainer.setLayoutColumnsCount(actionsList.size)
val adapter = IncidentActionButtonsListAdapter(actionsList, this)
binding.actionButtonsContainer.setAdapter(adapter)
binding.actionButtonsContainer.visibility = View.VISIBLE
My Adapter :
import android.graphics.Rect
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class IncidentActionButtonsListAdapter(
private val actionsList: List<IncidentAction>,
private val incidentActionButtonViewClickListener: IncidentActionButtonViewClickListener? = null
): RecyclerView.Adapter<IncidentActionButtonsListAdapter.IncidentActionButtonsListViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IncidentActionButtonsListViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_incident_action_button_item, parent, false)
return IncidentActionButtonsListViewHolder(view)
}
override fun onBindViewHolder(holder: IncidentActionButtonsListViewHolder, position: Int) {
actionsList[position].let { action ->
holder.tvIncidentActionTitle.text = holder.tvIncidentActionTitle.context.getString(action.text)
holder.itemView.setOnClickListener {
val incidentActionResult = IncidentActionResult(
code = action.id
)
incidentActionButtonViewClickListener?.onIncidentActionButtonViewClicked(incidentActionResult)
}
}
}
inner class IncidentActionButtonsListViewHolder(view: View): RecyclerView.ViewHolder(view) {
val container: LinearLayout = view.findViewById(R.id.container)
val tvIncidentActionTitle: TextView = view.findViewById(R.id.tvIncidentActionTitle)
}
override fun getItemCount(): Int = actionsList.size
}
interface IncidentActionButtonViewClickListener {
fun onIncidentActionButtonViewClicked(incidentActionResult: IncidentActionResult)
}
class IncidentActionButtonsItemDecorator (private val padding: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
)
{
super.getItemOffsets(outRect, view, parent, state)
outRect.top = padding
outRect.bottom = padding
outRect.left = padding
outRect.right = padding
}
}
The RecyclerView code :
class IncidentActionButtonView(
context: Context,
attrs: AttributeSet
): LinearLayout(context, attrs) {
var binding: LayoutIncidentActionListBinding = LayoutIncidentActionListBinding.inflate(LayoutInflater.from(context), this, true)
init {
val spacing = (context.resources.displayMetrics.density * 4).toInt() // converting dp to pixels
binding.list.addItemDecoration(IncidentActionButtonsItemDecorator(spacing)) // setting space between items in RecyclerView
}
fun setLayoutColumnsCount(numberOfActions: Int) {
var numberOfColumns = numberOfActions
val orientation = resources.configuration.orientation
// if phone is in landscape orientation we can accept up to 3 cols
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (numberOfColumns > 3) {
numberOfColumns = 3
}
} else { // else in portrait we can accept up to 2 cols
if (numberOfColumns > 2) {
numberOfColumns = 2
}
}
val layoutManager = GridLayoutManager(context, numberOfColumns)
binding.list.layoutManager = layoutManager
}
fun setAdapter(adapter: IncidentActionButtonsListAdapter) {
binding.list.adapter = adapter
binding.list.visibility = View.VISIBLE
}
}
The RecyclerView Layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/actionButtonsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/incident_list_background"
app:layout_constraintTop_toBottomOf="#id/tvTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
The cells layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/incident_action_button_background"
android:orientation="horizontal"
android:paddingLeft="#dimen/padding_small"
android:paddingRight="#dimen/padding_small"
android:paddingTop="#dimen/padding_extra_small"
android:paddingBottom="#dimen/padding_extra_small">
<TextView
style="#style/Theme.PortailAchat.Title1"
android:id="#+id/tvIncidentActionTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:text="#string/incident_await_new_delivery"
android:textAllCaps="true"
android:textAlignment="center"
android:layout_gravity="center"/>
</LinearLayout>
add this line of code inside the activity tag in manifest file:
android:windowSoftInputMode="adjustPan"

MDC Button MaterialShapeDrawable strange shadows and no ripple

Similar to the attachment in this issue, my button's corner shadows look pretty dodgy. But with a custom edge and rounded corner treatment, the button seems to lose elevation and there is no ripple / click effect. Any idea on what I have done wrong?
Material version is 1.1.0-alpha07
class CurvedEdgeTreatment (private val size: Float) : EdgeTreatment(), Cloneable {
public override fun clone(): EdgeTreatment {
return super<EdgeTreatment>.clone()
}
override fun getEdgePath(length: Float, center: Float, interpolation: Float, shapePath: ShapePath) {
shapePath.quadToPoint(center, -size * interpolation, length, 0f)
}
}
class ButtonActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_button)
val shapeAppearanceModel = ShapeAppearanceModel().apply {
setAllCorners(RoundedCornerTreatment(12.dpToPx(resources.displayMetrics).toFloat()))
setAllEdges(CurvedEdgeTreatment(3.dpToPx(resources.displayMetrics).toFloat()))
}
val backgroundDrawable = MaterialShapeDrawable(shapeAppearanceModel).apply {
setTint(ContextCompat.getColor(this#ButtonActivity, R.color.color_secondary))
shadowCompatibilityMode = SHADOW_COMPAT_MODE_ALWAYS
elevation = 12f
setUseTintColorForShadow(true)
paintStyle = Paint.Style.FILL
}
raisedContainedButton.background = backgroundDrawable
}
fun Int.dpToPx(displayMetrics: DisplayMetrics): Int = (this * displayMetrics.density).toInt()
fun Int.pxToDp(displayMetrics: DisplayMetrics): Int = (this / displayMetrics.density).toInt()
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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="match_parent"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
android:clipChildren="false"
android:clipToPadding="false">
<com.google.android.material.button.MaterialButton
android:id="#+id/raisedContainedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a button la la la la la la"/>
</FrameLayout>
</LinearLayout>

Categories

Resources