首先先预览一下实现的效果:灰色区域是设置的分割线,可以支持设置分割线的粗度和颜色属性:
-
<declare-styleable name="ZoomLayout">
-
<attr name="IntervalLineWidth" format="reference" />
-
<attr name="IntervalLineColor" format="reference" />
-
</declare-styleable>
实现思路:
1.首先在线性布局里的child中插入分割线view,根据设置的分割线粗和颜色进行设置。
2.增加分割线view的点击事件setOnTouchListener,比如,当手指向左移动时,缩小当前分割线左边子view的宽度,增大当前分割线右边子view的宽度,以实现分割线的左右移动和左右子view的横轴改变。联动拖动:当左边拖动到最小值(比如左边的子view 设置的minWidth是10dp)时,会判断左边所有的子view宽度是否达到了最小值,如果没有,则同时减少宽度,实现联动拖动的效果。
全部代码如下:
-
package com.ng.nguilib
-
-
import android.content.Context
-
import android.graphics.Color
-
import android.util.AttributeSet
-
import android.view.Gravity
-
import android.view.MotionEvent
-
import android.view.View
-
import android.view.ViewGroup
-
import android.widget.LinearLayout
-
-
/**
-
* 描述:可缩放的layout
-
* @author Jzn
-
* @date 2020/9/9
-
*/
-
class ZoomLayout constructor(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
-
//子layout列表
-
private
var mChildLayoutList: ArrayList<View> = arrayListOf()
-
private
var mIntervalList: ArrayList<View> = arrayListOf()
-
-
//起始点位置
-
private
var mStartX =
0f
-
private
var mStartY =
0f
-
-
//位移
-
private
var mIntervalX =
0f
-
private
var mIntervalY =
0f
-
-
//分割线是否添加过
-
private
var hadAdd =
false
-
-
//保存每个子view的宽度
-
private
var mChildWidthList: ArrayList<
Int> = arrayListOf()
-
private
var mChildHeightList: ArrayList<
Int> = arrayListOf()
-
-
//变化中的子view宽度
-
private
var mRunningXList: ArrayList<
Int> = arrayListOf()
-
private
var mRunningYList: ArrayList<
Int> = arrayListOf()
-
-
-
//params
-
private
var mIntervalLineWidth =
1
-
private
var mIntervalLineColor =
1
-
-
init {
-
val ta = context.obtainStyledAttributes(attrs, R.styleable.ZoomLayout)
-
mIntervalLineWidth = context.resources.getDimensionPixelOffset(ta.getResourceId(R.styleable.ZoomLayout_IntervalLineWidth, R.dimen.dd10))
-
mIntervalLineColor = ta.getColor(R.styleable.ZoomLayout_IntervalLineColor, Color.BLACK)
-
ta.recycle()
-
}
-
-
override
fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
-
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
-
refreshChildList()
-
addSplit()
-
refreshChildSizeList()
-
val maxSize =
if (measuredHeight > measuredWidth) measuredHeight
else measuredWidth
-
//修正分割线宽度
-
mIntervalList.forEachIndexed { _, child ->
-
val lp: ViewGroup.LayoutParams = child.layoutParams
-
if (orientation == HORIZONTAL) {
-
lp.height = maxSize
-
}
else
if (orientation == VERTICAL) {
-
lp.width = maxSize
-
}
-
child.layoutParams = lp
-
}
-
}
-
-
//刷新子view数组
-
private
fun refreshChildList() {
-
if (mChildLayoutList.size != childCount) {
-
mChildLayoutList.clear()
-
for (i
in
0 until childCount) {
-
val childView: View = getChildAt(i)
-
mChildLayoutList.add(childView)
-
}
-
}
-
}
-
-
//刷新子view size
-
private
fun refreshChildSizeList() {
-
if (mChildWidthList.size != childCount) {
-
mChildWidthList.clear()
-
mChildLayoutList.forEachIndexed { _, child ->
-
mChildWidthList.add(child.measuredWidth)
-
}
-
mRunningXList = mChildWidthList
-
}
-
if (mChildHeightList.size != childCount) {
-
mChildHeightList.clear()
-
mChildLayoutList.forEachIndexed { _, child ->
-
mChildHeightList.add(child.measuredHeight)
-
}
-
mRunningYList = mChildHeightList
-
}
-
}
-
-
//在子view中设置操作分割线
-
private
fun addSplit() {
-
if (mChildLayoutList.size == childCount && !hadAdd) {
-
//在子view的间距中添加操作view
-
mChildLayoutList.forEachIndexed { index, child ->
-
if (index < mChildLayoutList.size -
1) {
-
addIntervalLine(index, child)
-
}
-
}
-
hadAdd =
true
-
}
-
}
-
-
//增加垂直分割线
-
private
fun addIntervalLine(number: Int, child: View) {
-
val interValView = View(context)
-
interValView.setBackgroundColor(mIntervalLineColor)
-
var lp: ViewGroup.LayoutParams = LayoutParams(measuredWidth, mIntervalLineWidth)
-
if (orientation == HORIZONTAL) {
-
lp = LayoutParams(mIntervalLineWidth, measuredHeight)
-
}
else
if (orientation == VERTICAL) {
-
lp = LayoutParams(measuredWidth, mIntervalLineWidth)
-
}
-
interValView.layoutParams = lp
-
val tarGetLocation = IntArray(
2)
-
child.getLocationOnScreen(tarGetLocation)
-
if (orientation == HORIZONTAL) {
-
interValView.x = tarGetLocation[
0].toFloat()
-
}
else
if (orientation == VERTICAL) {
-
interValView.y = tarGetLocation[
1].toFloat()
-
}
-
val realIndex =
1 + number *
2
-
interValView.setOnTouchListener { view, motionEvent ->
-
when (motionEvent.action) {
-
MotionEvent.ACTION_DOWN -> {
-
mStartX = motionEvent.x
-
mStartY = motionEvent.y
-
}
-
MotionEvent.ACTION_UP -> {
-
refreshChildSizeList()
-
view.performClick()
-
}
-
}
-
mIntervalX = mStartX - motionEvent.x
-
mIntervalY = mStartY - motionEvent.y
-
if (orientation == HORIZONTAL) {
-
if (isChildValueLegal(mRunningXList[realIndex -
1] - mIntervalX.toInt(), realIndex -
1) &&
-
isChildValueLegal(mRunningXList[realIndex +
1] + mIntervalX.toInt(), realIndex +
1)
-
) {
-
mRunningXList[realIndex -
1] -= mIntervalX.toInt()
-
mRunningXList[realIndex +
1] += mIntervalX.toInt()
-
}
-
// 联动调整左边
-
if (!isChildValueLegal(mRunningXList[realIndex -
1] - mIntervalX.toInt(), realIndex -
1)) {
-
gravity = Gravity.START
-
var fixMulti =
0
-
if (realIndex -
2 >
0) {
-
for (index
in
0..realIndex -
2) {
-
//这里要判断是否是分割线
-
if (index %
2 ==
0 && isChildValueLegal(mRunningXList[index] - mIntervalX.toInt(), index)) {
-
mRunningXList[index] -= mIntervalX.toInt()
-
fixMulti++
-
}
-
}
-
mRunningXList[realIndex +
1] += mIntervalX.toInt() * fixMulti
-
}
-
}
-
//联动调整右边
-
if (!isChildValueLegal(mRunningXList[realIndex +
1] + mIntervalX.toInt(), realIndex +
1)) {
-
gravity = Gravity.END
-
var fixMulti =
0
-
for (index
in (realIndex +
2) until childCount) {
-
if (index %
2 ==
0 && isChildValueLegal(mRunningXList[index] + mIntervalX.toInt(), index)) {
-
mRunningXList[index] += mIntervalX.toInt()
-
fixMulti++
-
}
-
}
-
mRunningXList[realIndex -
1] -= mIntervalX.toInt() * fixMulti
-
}
-
}
else
if (orientation == VERTICAL) {
-
if (isChildValueLegal(mRunningYList[realIndex -
1] - mIntervalY.toInt(), realIndex -
1) &&
-
isChildValueLegal(mRunningYList[realIndex +
1] + mIntervalY.toInt(), realIndex +
1)) {
-
mRunningYList[realIndex -
1] -= mIntervalY.toInt()
-
mRunningYList[realIndex +
1] += mIntervalY.toInt()
-
}
-
// 联动调整上面
-
if (!isChildValueLegal(mRunningYList[realIndex -
1] - mIntervalY.toInt(), realIndex +
1)) {
-
gravity = Gravity.TOP
-
var fixMulti =
0
-
if (realIndex -
2 >
0) {
-
for (index
in
0..realIndex -
2) {
-
if (index %
2 ==
0 && isChildValueLegal(mRunningYList[index] - mIntervalY.toInt(), index)) {
-
mRunningYList[index] -= mIntervalY.toInt()
-
fixMulti++
-
}
-
}
-
mRunningYList[realIndex +
1] += mIntervalY.toInt() * fixMulti
-
}
-
}
-
// 联动调整下面
-
if (!isChildValueLegal(mRunningYList[realIndex +
1] + mIntervalY.toInt(), realIndex +
1)) {
-
gravity = Gravity.BOTTOM
-
var fixMulti =
0
-
for (index
in (realIndex +
2) until childCount) {
-
if (index %
2 ==
0 && isChildValueLegal(mRunningYList[index] + mIntervalY.toInt(), index)) {
-
mRunningYList[index] += mIntervalY.toInt()
-
fixMulti++
-
}
-
}
-
mRunningYList[realIndex -
1] -= mIntervalY.toInt() * fixMulti
-
}
-
}
-
mChildLayoutList.forEachIndexed { index, child ->
-
val childLp: LayoutParams = child.layoutParams
as LayoutParams
-
childLp.weight =
0f
-
if (orientation == HORIZONTAL) {
-
childLp.width = mRunningXList[index]
-
-
}
else
if (orientation == VERTICAL) {
-
childLp.height = mRunningYList[index]
-
}
-
-
child.layoutParams = childLp
-
}
-
//防止左越界
-
if (mChildLayoutList.size !=
0) {
-
mChildLayoutList[
0].x =
0f
-
}
-
true
-
}
-
mIntervalList.add(interValView)
-
addView(interValView, realIndex, lp)
-
}
-
-
private
fun isChildValueLegal(value: Int, index: Int):
Boolean {
-
val minZoom =
if (orientation == HORIZONTAL) {
-
mChildLayoutList[index].minimumWidth
-
}
else {
-
mChildLayoutList[index].minimumHeight
-
}
-
return value > minZoom
-
}
-
-
}
代码下载和效果预览地址:
https://github.com/jiangzhengnan/NguiLib
求start~求fork~
也欢迎提交~
转载:https://blog.csdn.net/qq_22770457/article/details/108560992
查看评论