Skip to content

Commit

Permalink
* fix wrap_content
Browse files Browse the repository at this point in the history
  • Loading branch information
angcyo committed Dec 9, 2022
1 parent f603106 commit e2a67c4
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 80 deletions.
52 changes: 44 additions & 8 deletions TabLayout/src/main/java/com/angcyo/tablayout/DslTabIndicator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
/**切换时是否需要动画的支持*/
var indicatorAnim = true

/**在获取锚点view的宽高时, 是否需要忽略对应的padding属性*/
var ignoreChildPadding: Boolean = true

init {
callback = tabLayout
}
Expand Down Expand Up @@ -199,6 +202,11 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
)
}

ignoreChildPadding = typedArray.getBoolean(
R.styleable.DslTabLayout_tab_indicator_ignore_child_padding,
!indicatorStyle.have(INDICATOR_STYLE_CENTER)
)

indicatorFlowStep =
typedArray.getInt(R.styleable.DslTabLayout_tab_indicator_flow_step, indicatorFlowStep)
indicatorEnableFlow = typedArray.getBoolean(
Expand Down Expand Up @@ -348,6 +356,24 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
}
}

open fun getChildTargetPaddingLeft(childView: View): Int =
if (ignoreChildPadding) childView.paddingLeft else 0

open fun getChildTargetPaddingRight(childView: View): Int =
if (ignoreChildPadding) childView.paddingRight else 0

open fun getChildTargetPaddingTop(childView: View): Int =
if (ignoreChildPadding) childView.paddingTop else 0

open fun getChildTargetPaddingBottom(childView: View): Int =
if (ignoreChildPadding) childView.paddingBottom else 0

open fun getChildTargetWidth(childView: View): Int =
if (ignoreChildPadding) childView.viewDrawWidth else childView.measuredWidth

open fun getChildTargetHeight(childView: View): Int =
if (ignoreChildPadding) childView.viewDrawHeight else childView.measuredHeight

/**
* [childview]对应的中心x坐标
* */
Expand All @@ -360,13 +386,19 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
when (gravity) {
INDICATOR_GRAVITY_START -> childView.left
INDICATOR_GRAVITY_END -> childView.right
else -> childView.left + childView.paddingLeft + childView.viewDrawWidth / 2
else -> childView.left + getChildTargetPaddingLeft(childView) + getChildTargetWidth(
childView
) / 2
}
} else {
when (gravity) {
INDICATOR_GRAVITY_START -> childView.left + contentChildView.left
INDICATOR_GRAVITY_END -> childView.left + contentChildView.right
else -> childView.left + contentChildView.left + contentChildView.paddingLeft + contentChildView.viewDrawWidth / 2
else -> childView.left + contentChildView.left + getChildTargetPaddingLeft(
contentChildView
) + getChildTargetWidth(
contentChildView
) / 2
}
}
}
Expand All @@ -383,13 +415,19 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
when (gravity) {
INDICATOR_GRAVITY_START -> childView.top
INDICATOR_GRAVITY_END -> childView.bottom
else -> childView.top + childView.paddingTop + childView.viewDrawHeight / 2
else -> childView.top + getChildTargetPaddingTop(childView) + getChildTargetHeight(
childView
) / 2
}
} else {
when (gravity) {
INDICATOR_GRAVITY_START -> childView.top + contentChildView.top
INDICATOR_GRAVITY_END -> childView.top + childView.bottom
else -> childView.top + contentChildView.top + contentChildView.paddingTop + contentChildView.viewDrawHeight / 2
else -> childView.top + contentChildView.top + getChildTargetPaddingTop(
contentChildView
) + getChildTargetHeight(
contentChildView
) / 2
}
}
}
Expand All @@ -403,8 +441,7 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
when (indicatorWidth) {
ViewGroup.LayoutParams.WRAP_CONTENT -> {
tabLayout.dslSelector.visibleViewList.getOrNull(index)?.also { childView ->
result =
indicatorContentView(childView)?.viewDrawWidth ?: childView.viewDrawWidth
result = getChildTargetWidth(indicatorContentView(childView) ?: childView)
}
}
ViewGroup.LayoutParams.MATCH_PARENT -> {
Expand All @@ -423,8 +460,7 @@ open class DslTabIndicator(val tabLayout: DslTabLayout) : DslGradientDrawable()
when (indicatorHeight) {
ViewGroup.LayoutParams.WRAP_CONTENT -> {
tabLayout.dslSelector.visibleViewList.getOrNull(index)?.also { childView ->
result =
indicatorContentView(childView)?.viewDrawHeight ?: childView.viewDrawHeight
result = getChildTargetHeight(indicatorContentView(childView) ?: childView)
}
}
ViewGroup.LayoutParams.MATCH_PARENT -> {
Expand Down
135 changes: 63 additions & 72 deletions TabLayout/src/main/java/com/angcyo/tablayout/DslTabLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import android.widget.LinearLayout
import android.widget.OverScroller
import android.widget.TextView
import androidx.core.view.GestureDetectorCompat
import androidx.core.view.GravityCompat
import androidx.core.view.ViewCompat
import kotlin.math.abs
import kotlin.math.max
Expand Down Expand Up @@ -660,16 +661,17 @@ open class DslTabLayout(
val visibleChildList = dslSelector.visibleViewList
val visibleChildCount = visibleChildList.size

//控制最小大小
val tabMinHeight = if (suggestedMinimumHeight > 0) {
suggestedMinimumHeight
} else {
itemDefaultHeight
}

if (visibleChildCount == 0) {
setMeasuredDimension(
getDefaultSize(suggestedMinimumWidth, widthMeasureSpec),
getDefaultSize(
if (suggestedMinimumHeight > 0) {
suggestedMinimumHeight
} else {
itemDefaultHeight
}, heightMeasureSpec
)
getDefaultSize(tabMinHeight, heightMeasureSpec)
)
return
}
Expand All @@ -682,19 +684,10 @@ open class DslTabLayout(

_maxConvexHeight = 0

//child高度测量模式
var childHeightSpec: Int = -1
var childWidthSpec: Int = -1

//记录child最大的height, 用来实现tabLayout wrap_content
var childMaxHeight = 0 //child最大的高度

childHeightSpec = if (heightMode == MeasureSpec.EXACTLY) {
//固定高度
exactlyMeasure(heightSize - paddingTop - paddingBottom)
} else {
atmostMeasure(Int.MAX_VALUE)
}
//记录child最大的height, 用来实现tabLayout wrap_content, 包括突出的大小
var childMaxHeight = tabMinHeight //child最大的高度

if (heightMode == MeasureSpec.UNSPECIFIED) {
if (heightSize == 0) {
Expand Down Expand Up @@ -776,74 +769,57 @@ open class DslTabLayout(

_childAllWidthSum = 0

var wrapContentHeight = false

//没有设置weight属性的child宽度总和, 用于计算剩余空间
var allChildUsedWidth = 0

fun measureChild(childView: View) {
fun measureChild(childView: View, heightSpec: Int? = null) {
val lp = childView.layoutParams as LayoutParams

//横向布局, 不支持竖向margin支持
lp.topMargin = 0
lp.bottomMargin = 0

val childConvexHeight = lp.layoutConvexHeight
//child高度测量模式
var childHeightSpec: Int = -1

val widthHeight = calcLayoutWidthHeight(
lp.layoutWidth, lp.layoutHeight,
widthSize, heightSize, 0, 0
)

//计算高度测量模式
wrapContentHeight = false
if (childHeightSpec == -1) {
if (heightMode == MeasureSpec.EXACTLY) {
//固定高度
childHeightSpec =
exactlyMeasure(heightSize - paddingTop - paddingBottom - lp.topMargin - lp.bottomMargin)
} else {
if (widthHeight[1] > 0) {
heightSize = widthHeight[1]
childHeightSpec = exactlyMeasure(heightSize)
heightSize += paddingTop + paddingBottom
}
}

if (childHeightSpec == -1) {
if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT) {

heightSize = if (suggestedMinimumHeight > 0) {
suggestedMinimumHeight
} else {
childHeightSpec = if (lp.height == ViewGroup.LayoutParams.MATCH_PARENT) {
exactlyMeasure(tabMinHeight)
} else {
itemDefaultHeight
atmostMeasure(Int.MAX_VALUE)
}

childHeightSpec = exactlyMeasure(heightSize)

heightSize += paddingTop + paddingBottom
} else {
childHeightSpec = atmostMeasure(heightSize)
wrapContentHeight = true
}
}

val childConvexHeight = lp.layoutConvexHeight

//...end

//计算宽度测量模式
childWidthSpec //no op

if (childConvexHeight > 0) {
_maxConvexHeight = max(_maxConvexHeight, childConvexHeight)
//需要凸起
val childConvexHeightSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(childHeightSpec) + childConvexHeight,
MeasureSpec.getMode(childHeightSpec)
)
childView.measure(childWidthSpec, childConvexHeightSpec)
if (heightSpec != null) {
childView.measure(childWidthSpec, heightSpec)
} else {
childView.measure(childWidthSpec, childHeightSpec)
}

if (wrapContentHeight) {
heightSize = childView.measuredHeight
childHeightSpec = exactlyMeasure(heightSize)
heightSize += paddingTop + paddingBottom
if (childConvexHeight > 0) {
_maxConvexHeight = max(_maxConvexHeight, childConvexHeight)
//需要凸起
val spec = exactlyMeasure(childView.measuredHeight + childConvexHeight)
childView.measure(childWidthSpec, spec)
}
childMaxHeight = max(childMaxHeight, childView.measuredHeight)
}

visibleChildList.forEachIndexed { index, childView ->
Expand Down Expand Up @@ -919,9 +895,14 @@ open class DslTabLayout(

if (heightMode == MeasureSpec.AT_MOST) {
//wrap_content 情况下, 重新测量所有子view
childHeightSpec = exactlyMeasure(max(childMaxHeight, suggestedMinimumHeight))
val childHeightSpec = exactlyMeasure(
max(
childMaxHeight - _maxConvexHeight,
suggestedMinimumHeight - paddingTop - paddingBottom
)
)
visibleChildList.forEach { childView ->
measureChild(childView)
measureChild(childView, childHeightSpec)
}
}

Expand All @@ -936,7 +917,10 @@ open class DslTabLayout(
itemDefaultHeight
}
} else if (heightMode != MeasureSpec.EXACTLY) {
heightSize = max(childMaxHeight + paddingTop + paddingBottom, suggestedMinimumHeight)
heightSize = max(
childMaxHeight - _maxConvexHeight + paddingTop + paddingBottom,
suggestedMinimumHeight
)
}

setMeasuredDimension(widthSize, heightSize + _maxConvexHeight)
Expand Down Expand Up @@ -1064,6 +1048,7 @@ open class DslTabLayout(
lp.marginEnd = 0

val childConvexHeight = lp.layoutConvexHeight
_maxConvexHeight = max(_maxConvexHeight, childConvexHeight)

val widthHeight = calcLayoutWidthHeight(
lp.layoutWidth, lp.layoutHeight,
Expand Down Expand Up @@ -1103,7 +1088,6 @@ open class DslTabLayout(
childHeightSpec //no op

if (childConvexHeight > 0) {
_maxConvexHeight = max(_maxConvexHeight, childConvexHeight)
//需要凸起
val childConvexWidthSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(childWidthSpec) + childConvexHeight,
Expand Down Expand Up @@ -1261,6 +1245,7 @@ open class DslTabLayout(
visibleChildList.forEachIndexed { index, childView ->

val lp = childView.layoutParams as LayoutParams
val verticalGravity = lp.gravity and Gravity.VERTICAL_GRAVITY_MASK

if (isRtl) {
right -= lp.marginEnd
Expand All @@ -1279,15 +1264,14 @@ open class DslTabLayout(
}
}

childBottom = if (lp.gravity.have(Gravity.CENTER_VERTICAL)) {
measuredHeight - paddingBottom -
childBottom = when (verticalGravity) {
Gravity.CENTER_VERTICAL -> measuredHeight - paddingBottom -
((measuredHeight - paddingTop - paddingBottom - _maxConvexHeight) / 2 -
childView.measuredHeight / 2)
} else {
measuredHeight - paddingBottom
Gravity.BOTTOM -> measuredHeight - paddingBottom
else -> paddingTop + lp.topMargin + childView.measuredHeight
}

/*默认垂直居中显示*/
if (isRtl) {
childView.layout(
right - childView.measuredWidth,
Expand Down Expand Up @@ -1332,6 +1316,9 @@ open class DslTabLayout(
visibleChildList.forEachIndexed { index, childView ->

val lp = childView.layoutParams as LayoutParams
val layoutDirection = 0
val absoluteGravity = GravityCompat.getAbsoluteGravity(lp.gravity, layoutDirection)
val horizontalGravity = absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK

top += lp.topMargin

Expand All @@ -1341,11 +1328,11 @@ open class DslTabLayout(
}
}

childLeft = if (lp.gravity.have(Gravity.CENTER_HORIZONTAL)) {
paddingStart + ((measuredWidth - paddingStart - paddingEnd - _maxConvexHeight) / 2 -
childLeft = when (horizontalGravity) {
Gravity.CENTER_HORIZONTAL -> paddingStart + ((measuredWidth - paddingStart - paddingEnd - _maxConvexHeight) / 2 -
childView.measuredWidth / 2)
} else {
paddingStart
Gravity.RIGHT -> measuredWidth - paddingRight - childView.measuredWidth - lp.rightMargin
else -> paddingLeft + lp.leftMargin
}

/*默认水平居中显示*/
Expand Down Expand Up @@ -1433,7 +1420,11 @@ open class DslTabLayout(
a.recycle()

if (gravity == UNSPECIFIED_GRAVITY) {
gravity = Gravity.CENTER
gravity = if (layoutConvexHeight > 0) {
Gravity.BOTTOM
} else {
Gravity.CENTER
}
}
}

Expand Down
1 change: 1 addition & 0 deletions TabLayout/src/main/res/values/attr_dsl_tab_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<attr name="tab_indicator_gradient_colors" format="string" />
<attr name="tab_indicator_gradient_start_color" format="color" />
<attr name="tab_indicator_gradient_end_color" format="color" />
<attr name="tab_indicator_ignore_child_padding" format="boolean" />
<!--end...-->

<!--TabLayoutConfig 相关属性-->
Expand Down

0 comments on commit e2a67c4

Please sign in to comment.