年前最后一发:带分割线的LinearLayout
2017-01-23 本文已影响1528人
Kisson
前言
分割线场景在开发过程中,界面中条目间都需要我们设置分割线。大多时候,我们都通过如下布局代码片段设置:
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#cccccc"/>
如上写法虽也方便,但会导致出现很多此类重复代码。另外,当我们需要隐藏其中某一条目之时,分割线同样也需做隐藏处理,较为繁琐。
因此,针对此类场景,我在LinearLayout可以设置分割线样式的属性的基础上,加以改进,提炼出使用场景更广的DividerLinearLayout。
简介
项目地址:DividerLinearLayout
LinearLayout在Android3.0以上版本支持设置分割线样式的属性。关于该属性的具体使用方法,本文不在叙述。
DividerLinearLayout效果图如下:
有人可能会说,既然LinearLayout本身支持设置分割线,为啥你要多此一举。因为LinearLayout的分割线,仅支持四种模式。
SHOW_DIVIDER_NONE,无分割线。
SHOW_DIVIDER_BEGINNING,第一个可见child view前添加分割线。
SHOW_DIVIDER_MIDDLE,在两个可见View中间添加分割线。
SHOW_DIVIDER_END,最后一个可见child view前添加分割线。
LinearLayout的分割线无法同时设置以上所有模式。
另外LinearLayout的分割线是Drawable格式(比较重),大多情况下我们仅仅是要设置一条线而已。
DividerLayout支持的属性如下:
1.设置分割线颜色。
2.设置分割线的宽度。
3.设置头分割线是否可见。
4.设置尾分割线是否可见。
5.设置头分割线的padding。
6.设置尾分割线的padding。
7.支持代码动态设置以上所有属性。
源码片段
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import com.example.testui.R;
/**
* Created by chenjiawei on 16/12/8.
*/
public class DividerLinearLayout extends LinearLayout {
private int mDividerWidth = 0;
private boolean mHeaderDividerEnable = false;
private boolean mFooterDividerEnable = false;
private int mDividerColor;
private int mHeaderDividerPaddingEnd;
private int mHeaderDividerPaddingStart;
private int mFooterDividerPaddingEnd;
private int mFooterDividerPaddingStart;
private GradientDrawable mDividerDrawable;
public DividerLinearLayout(Context context) {
super(context);
initDividerDrawable();
}
public DividerLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
resolveAttributeSet(attrs);
adjustPadding();
initDividerDrawable();
}
public DividerLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
resolveAttributeSet(attrs);
adjustPadding();
initDividerDrawable();
}
private void resolveAttributeSet(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.borderLinearLayout);
for (int i = 0; i < typedArray.getIndexCount(); i++) {
int index = typedArray.getIndex(i);
switch (index) {
case R.styleable.borderLinearLayout_dividerColor:
mDividerColor = typedArray.getColor(index, getResources().getColor(R.color.defaultDividerColor));
break;
case R.styleable.borderLinearLayout_dividerWidth:
mDividerWidth = (int) typedArray.getDimension(index, 0);
break;
case R.styleable.borderLinearLayout_footerDividerEnable:
mHeaderDividerEnable = typedArray.getBoolean(index, false);
break;
case R.styleable.borderLinearLayout_headerDividerEnable:
mFooterDividerEnable = typedArray.getBoolean(index, false);
break;
case R.styleable.borderLinearLayout_headerDividerPaddingStart:
mHeaderDividerPaddingStart = (int) typedArray.getDimension(index, 0);
break;
case R.styleable.borderLinearLayout_headerDividerPaddingEnd:
mHeaderDividerPaddingEnd = (int) typedArray.getDimension(index, 0);
break;
case R.styleable.borderLinearLayout_footerDividerPaddingStart:
mFooterDividerPaddingStart = (int) typedArray.getDimension(index, 0);
break;
case R.styleable.borderLinearLayout_footerDividerPaddingEnd:
mFooterDividerPaddingEnd = (int) typedArray.getDimension(index, 0);
break;
default:
break;
}
}
typedArray.recycle();
}
void initDividerDrawable() {
setShowDividers(SHOW_DIVIDER_MIDDLE);
setDividerDrawableAttributeSet();
}
void setDividerDrawableAttributeSet() {
mDividerDrawable = new GradientDrawable();
mDividerDrawable.setColor(mDividerColor);
mDividerDrawable.setShape(GradientDrawable.RECTANGLE);
if (getOrientation() == VERTICAL) {
mDividerDrawable.setSize(getMeasuredWidth(), mDividerWidth);
} else {
mDividerDrawable.setSize(mDividerWidth, getMeasuredHeight());
}
setDividerDrawable(mDividerDrawable);
}
void adjustPadding() {
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mHeaderDividerEnable) {
drawHeaderDivider(canvas);
}
if (mFooterDividerEnable) {
drawFooterDivider(canvas);
}
}
@Override
public void setPadding(int left, int top, int right, int bottom) {
if (mHeaderDividerEnable) {
if (getOrientation() == VERTICAL) {
top = mDividerWidth + top;
} else {
left = mDividerWidth + left;
}
}
if (mFooterDividerEnable) {
if (getOrientation() == VERTICAL) {
bottom = mDividerWidth + bottom;
} else {
right = mDividerWidth + right;
}
}
super.setPadding(left, top, right, bottom);
}
/**
* Set the visible state of header divider
*
* @param visible True if the header divider is Shown, false otherwise
*/
public void showHeaderDivider(boolean visible) {
if (mHeaderDividerEnable != visible) {
resetPadding();
this.mHeaderDividerEnable = visible;
adjustPadding();
postInvalidate();
}
}
/**
* Set the visible state of footer divider
*
* @param visible True if the footer divider is Shown, false otherwise
*/
public void showFooterDivider(boolean visible) {
if (mFooterDividerEnable != visible) {
resetPadding();
this.mFooterDividerEnable = visible;
adjustPadding();
postInvalidate();
}
}
void resetPadding() {
if (mFooterDividerEnable && mDividerWidth > 0) {
if (getOrientation() == VERTICAL) {
super.setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() - mDividerWidth);
} else {
super.setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight() - mDividerWidth, getPaddingBottom());
}
}
if (mHeaderDividerEnable && mDividerWidth > 0) {
if (getOrientation() == VERTICAL) {
super.setPadding(getPaddingLeft(), getPaddingTop() - mDividerWidth, getPaddingRight(), getPaddingBottom());
} else {
super.setPadding(getPaddingLeft() - mDividerWidth, getPaddingTop(), getPaddingRight(), getPaddingBottom());
}
}
}
/**
* Set the width value of divider
*
* @param width the divider width in px
*/
public void setDividerWidth(int width) {
if (mDividerWidth != width) {
resetPadding();
this.mDividerWidth = width;
adjustPadding();
setDividerDrawableAttributeSet();
}
}
/**
* Set the color value of divider
*
* @param color the color of divider
*/
public void setDividerColor(int color) {
if (mDividerColor != color) {
this.mDividerColor = color;
setDividerDrawableAttributeSet();
postInvalidate();
}
}
/**
* Set the padding of header divider
*
* @param start the start padding in pixels
* @param end the end padding in pixels
*/
public void setHeaderDividerPadding(int start, int end) {
if (mHeaderDividerPaddingStart != start || mHeaderDividerPaddingEnd != end) {
this.mHeaderDividerPaddingStart = start;
this.mHeaderDividerPaddingEnd = end;
postInvalidate();
}
}
/**
* Set the padding of footer divider
*
* @param start the start padding in pixels
* @param end the end padding in pixels
*/
public void setFooterDividerPadding(int start, int end) {
if (mFooterDividerPaddingStart != start || mFooterDividerPaddingEnd != end) {
this.mFooterDividerPaddingStart = start;
this.mFooterDividerPaddingEnd = end;
postInvalidate();
}
}
private void drawHeaderDivider(Canvas canvas) {
View child = findFirstVisibleView();
if (child != null) {
if (getOrientation() == VERTICAL) {
drawHeaderDividerVertical(child, canvas);
} else {
drawHeaderDividerHorizontal(child, canvas);
}
}
}
private void drawHeaderDividerVertical(View child, Canvas canvas) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int top = child.getTop() - lp.topMargin - mDividerWidth;
mDividerDrawable.setBounds(mHeaderDividerPaddingStart, top,
getMeasuredWidth() - mHeaderDividerPaddingEnd, top + mDividerWidth);
mDividerDrawable.draw(canvas);
}
private void drawHeaderDividerHorizontal(View child, Canvas canvas) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int left = child.getLeft() - lp.leftMargin - mDividerWidth;
mDividerDrawable.setBounds(left, mHeaderDividerPaddingStart, left + mDividerWidth, getMeasuredHeight() - mHeaderDividerPaddingEnd);
mDividerDrawable.draw(canvas);
}
private void drawFooterDivider(Canvas canvas) {
View child = findLastVisibleView();
if (child != null) {
if (getOrientation() == VERTICAL) {
drawFooterDividerVertical(child, canvas);
} else {
drawFooterDividerHorizontal(child, canvas);
}
}
}
private void drawFooterDividerVertical(View child, Canvas canvas) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int bottom = child.getBottom() + lp.bottomMargin + mDividerWidth;
mDividerDrawable.setBounds(mFooterDividerPaddingStart, bottom - mDividerWidth,
getMeasuredWidth() - mFooterDividerPaddingEnd, bottom);
mDividerDrawable.draw(canvas);
}
private void drawFooterDividerHorizontal(View child, Canvas canvas) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int right = child.getRight() + lp.rightMargin + mDividerWidth;
mDividerDrawable.setBounds(right - mDividerWidth, mFooterDividerPaddingStart, right, getMeasuredHeight() - mFooterDividerPaddingEnd);
mDividerDrawable.draw(canvas);
}
View findFirstVisibleView() {
if (getChildCount() > 0) {
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i) != null && getChildAt(i).getVisibility() != GONE) {
return getChildAt(i);
}
}
}
return null;
}
View findLastVisibleView() {
if (getChildCount() > 0) {
for (int i = getChildCount() - 1; i >= 0; i--) {
if (getChildAt(i) != null && getChildAt(i).getVisibility() != GONE) {
return getChildAt(i);
}
}
}
return null;
}
}
最后
欢迎喜欢点赞,谢谢支持!