Android 사용자 정의 컨트롤 구현 시간 축
프로젝트 에 필요 한 것 이 있 기 때문에 간단하게 하 나 를 포장 하고 기록 해서 github 에 올 릴 시간 이 있 습 니 다.
1.사용자 정의 속성 을 먼저 증가:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="global_TimelineLayout">
<!-- -->
<attr name="global_line_margin_left" format="dimension" />
<!-- -->
<attr name="global_line_margin_top" format="dimension" />
<!-- -->
<attr name="global_line_stroke_width" format="dimension" />
<!-- -->
<attr name="global_line_color" format="color" />
<!-- -->
<attr name="global_point_inner_size" format="dimension" />
<attr name="global_point_out_size" format="dimension" />
<!-- -->
<attr name="global_point_margin_top" format="dimension" />
<!-- -->
<attr name="global_point_inner_color" format="color" />
<attr name="global_point_out_color" format="color" />
<!-- -->
<attr name="global_icon_src" format="reference" />
<!-- -->
<attr name="global_dash_gap" format="dimension" />
<attr name="global_dash_width" format="dimension" />
</declare-styleable>
</resources>
2.사용자 정의 시간 축 종류:
/**
*
* <p>The following snippet shows how to include a linear layout in your layout XML file:</p>
*
* <com.taoche.mars.commonres.widget.TimelineLayout
android:id="@+id/tl_02"
android:layout_width="40dp"
android:layout_height="match_parent"
app:global_line_margin_left="10dp"
app:global_line_margin_top="0dp"
app:global_point_margin_top="10dp"
app:global_point_inner_color="#377CFF"
app:global_point_out_color="#FFE8F0FF"
app:global_point_out_size="8dp"
app:global_point_inner_size="4dp"
app:global_dash_width="8dp"
app:global_dash_gap="2dp"
app:global_line_color="#C9DCFF">
</com.taoche.mars.commonres.widget.TimelineLayout>
*
* <p>The following snippet shows how to java file:</p>
* timelineLayout.setPointMarginTop(10)
timelineLayout.setLineMarginTop(10)
timelineLayout.setPointMarginTop(40)
timelineLayout.setInterrupt(true)
*/
class TimeLinearLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
private var mContext: Context? = null
private var mLineMarginLeft: Int = 10
private var mLineMarginTop: Int = 0
private var mPointMarginTop: Int = 0
private var mLineStrokeWidth: Int = 2
private var mLineColor: Int = 0
//
private var mPointInnerSize: Int = 8
//
private var mPointOutSize: Int = 18
//
private var mPointInnerColor: Int = 0
//
private var mPointOutColor: Int = 0
//
private var mDashWidth: Int = 0
//
private var mDashGap: Int = 0
//
private var mInterrupt: Boolean = false
private var mIcon: Bitmap? = null
//
private var mLinePaint: Paint? = null
//
private var mPointPaint: Paint? = null
//
private var mFirstX = 0
private var mFirstY = 0
//
private var mLastX = 0
private var mLastY = 0
init {
setLayerType(View.LAYER_TYPE_SOFTWARE, null) //
val ta = context.obtainStyledAttributes(attrs, R.styleable.global_TimelineLayout)
mLineMarginLeft = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_line_margin_left, 10)
mLineMarginTop = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_line_margin_top, 0)
mPointMarginTop = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_point_margin_top, 0)
mLineStrokeWidth = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_line_stroke_width, 2)
mLineColor = ta.getColor(R.styleable.global_TimelineLayout_global_line_color, -0xc22e5b)
mPointInnerSize = ta.getDimensionPixelSize(R.styleable.global_TimelineLayout_global_point_inner_size, 8)
mPointOutSize = ta.getDimensionPixelSize(R.styleable.global_TimelineLayout_global_point_out_size, 18)
mPointInnerColor = ta.getColor(R.styleable.global_TimelineLayout_global_point_inner_color, -0xc22e5b)
mPointOutColor = ta.getColor(R.styleable.global_TimelineLayout_global_point_out_color, -0x170f01)
mDashGap = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_dash_gap, 0)
mDashWidth = ta.getDimensionPixelOffset(R.styleable.global_TimelineLayout_global_dash_width, 0)
val iconRes = ta.getResourceId(R.styleable.global_TimelineLayout_global_icon_src, View.NO_ID)
if (iconRes > View.NO_ID) {
val drawable = ContextCompat.getDrawable(context,iconRes) as? BitmapDrawable
if (drawable != null) {
mIcon = drawable.bitmap
}
}
ta.recycle()
setWillNotDraw(false)
initView(context)
}
fun setLineMarginTop(lineMarginTop:Int){
this.mLineMarginTop = lineMarginTop
}
fun setPointMarginTop(pointMarginTop:Int){
this.mPointMarginTop = pointMarginTop
}
fun setInterrupt(interrupt:Boolean){
this.mInterrupt = interrupt
}
private fun initView(context: Context) {
mContext = context
mLinePaint = Paint()
mLinePaint?.apply {
isAntiAlias = true
isDither = true
color = mLineColor
strokeWidth = mLineStrokeWidth.toFloat()
style = Paint.Style.FILL_AND_STROKE
//
if (mDashGap > 0 && mDashWidth > 0) {
//mLinePaint.setPathEffect(new DashPathEffect(new float[]{20,5}, 20));
pathEffect = DashPathEffect(floatArrayOf(mDashWidth.toFloat(), mDashGap.toFloat()), mDashWidth.toFloat())
}
}
mPointPaint = Paint()
mPointPaint?.apply {
isAntiAlias = true
isDither = true
color = mPointInnerColor
style = Paint.Style.FILL
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
drawTimeline(canvas)
}
private fun drawTimeline(canvas: Canvas) {
drawBetweenLine(canvas)
drawFirstPoint(canvas)
drawLastIcon(canvas)
}
private fun drawFirstPoint(canvas: Canvas) {
val top = top
mFirstX = paddingLeft + mLineMarginLeft + max(mPointOutSize, mPointInnerSize)
mFirstY = top + paddingTop + mPointMarginTop + max(mPointOutSize, mPointInnerSize)
//
mPointPaint?.color = mPointOutColor
canvas.drawCircle(mFirstX.toFloat(), mFirstY.toFloat(), mPointOutSize.toFloat(), mPointPaint)
//
mPointPaint?.color = mPointInnerColor
canvas.drawCircle(mFirstX.toFloat(), mFirstY.toFloat(), mPointInnerSize.toFloat(), mPointPaint)
}
private fun drawLastIcon(canvas: Canvas) {
/*if (child != null) {
int top = child.getTop();
mLastX = mLineMarginLeft;
mLastY = top + child.getPaddingTop() + mLineMarginTop;
//
canvas.drawBitmap(mIcon, mLastX - (mIcon.getWidth() >> 1), mLastY, null);
}*/
val top = top
mLastX = mLineMarginLeft + paddingLeft
mLastY = top + paddingTop + mLineMarginTop
//
if (mIcon != null) {
canvas.drawBitmap(mIcon, mLastX - (mIcon!!.width shr 1).toFloat(), height - mIcon!!.height.toFloat(), null)
}
}
private fun drawBetweenLine(canvas: Canvas) {
val top = top
mFirstX = paddingLeft + mLineMarginLeft + max(mPointOutSize, mPointInnerSize)
mFirstY = top + paddingTop + mLineMarginTop
mLastX = paddingLeft + mLineMarginLeft + max(mPointOutSize, mPointInnerSize)
mLastY = if(!mInterrupt) {top + paddingTop + mLineMarginTop + height} else mPointMarginTop
// ,
canvas.drawLine(mFirstX.toFloat(), mFirstY.toFloat(), mLastX.toFloat(), mLastY.toFloat(), mLinePaint)
//
//val y = top + paddingTop + mLineMarginTop + mPointInnerSize
//canvas.drawCircle(mFirstX, y, mPointSize, mPointPaint);
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val mode = MeasureSpec.getMode(widthMeasureSpec)
var measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = MeasureSpec.getSize(heightMeasureSpec)
if (mode == MeasureSpec.AT_MOST) {
measuredWidth = paddingLeft + mLineMarginLeft + max(mPointOutSize, mPointInnerSize) * 2
}
setMeasuredDimension(measuredWidth, measuredHeight)
}
}
레이아웃 에서 직접 참조 할 수 있 습 니 다.다음 과 같 습 니 다.
<com.example.demo1224.TimelineLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:line_margin_left="25dp"
app:line_margin_top="0dp"
app:point_margin_top="10dp"
app:point_inner_color="#377CFF"
app:point_out_color="#FFE8F0FF"
app:point_out_size="8dp"
app:point_inner_size="4dp"
app:dash_width="8dp"
app:dash_gap="2dp"
app:line_color="#C9DCFF"
android:orientation="vertical"
android:background="@android:color/white">
</com.example.demo1224.TimelineLayout>
코드 에 관련 속성 을 동적 으로 설정 할 수도 있 습 니 다(관련 속성 설명,사용자 정의 속성 에 설명 이 있 습 니 다).
timelineLayout.setPointMarginTop(10)
timelineLayout.setLineMarginTop(10)
timelineLayout.setPointMarginTop(40)
timelineLayout.setInterrupt(true)
참고 하 시기 바 랍 니 다!이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.