欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義控件實現(xiàn)時間軸

 更新時間:2021年04月26日 14:05:07   作者:夢想不只是夢與想  
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實現(xiàn)時間軸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android自定義控件實現(xiàn)時間軸的具體代碼,供大家參考,具體內(nèi)容如下

由于項目中有需求,就簡單的封裝一個,先記錄一下,有時間上傳到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" />
        <!--圖標(biāo)-->
        <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
    //內(nèi)圓半徑
    private var mPointInnerSize: Int = 8
    //外圓半徑
    private var mPointOutSize: Int = 18
    //內(nèi)圓顏色
    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
 
    //最后一個圖標(biāo)的位置
    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
            //虛線設(shè)置
            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)
 
        //畫圓外環(huán)
        mPointPaint?.color = mPointOutColor
        canvas.drawCircle(mFirstX.toFloat(), mFirstY.toFloat(), mPointOutSize.toFloat(), mPointPaint)
        //畫圓內(nèi)環(huán)
        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
 
        //從開始的點到最后的圖標(biāo)之間,畫一條線
        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>

也可以在代碼里面動態(tài)設(shè)置相關(guān)屬性(相關(guān)屬性注釋,在自定義屬性時有說明):

timelineLayout.setPointMarginTop(10)
    timelineLayout.setLineMarginTop(10)
    timelineLayout.setPointMarginTop(40)
    timelineLayout.setInterrupt(true)

僅供大家參考!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例

    android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例

    在平時開發(fā)應(yīng)用的時候,經(jīng)常會遇到列表排序、滑動刪除的需求。這篇文章主要介紹了android的RecyclerView實現(xiàn)拖拽排序和側(cè)滑刪除示例,有興趣的可以了解一下。
    2017-02-02
  • 代碼分析Android消息機(jī)制

    代碼分析Android消息機(jī)制

    本文通過代碼實例詳細(xì)分析了Android消息機(jī)制的相關(guān)知識點,對此有需要的朋友可以參考學(xué)習(xí)下。
    2018-03-03
  • Kotlin實現(xiàn)半圓形進(jìn)度條的方法示例

    Kotlin實現(xiàn)半圓形進(jìn)度條的方法示例

    這篇文章主要給大家介紹了關(guān)于Kotlin實現(xiàn)半圓形進(jìn)度條的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Android中Root權(quán)限獲取的簡單代碼

    Android中Root權(quán)限獲取的簡單代碼

    那么我們在Android開發(fā)中如何獲取Android的Root權(quán)限呢?下面是主要的簡單代碼。
    2013-06-06
  • Android RecyclerView自由拖動item的實現(xiàn)代碼

    Android RecyclerView自由拖動item的實現(xiàn)代碼

    這篇文章主要介紹了Android RecyclerView自由拖動item的實現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • Android中CountDownTimer倒計時器用法實例

    Android中CountDownTimer倒計時器用法實例

    這篇文章主要介紹了Android中CountDownTimer倒計時器用法,以實例形式分析了Android中CountDownTimer類的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • Android Activity Results API代替onActivityResult處理頁面數(shù)據(jù)

    Android Activity Results API代替onActivityResul

    說到onActivityResult,我們已經(jīng)非常熟悉來,通過在A activity啟動B activity并且傳入數(shù)據(jù)到B中,然后在A中通過onActivityResult來接收B中返回的數(shù)據(jù)。在最新的activity-ktx的beta版本中,谷歌已經(jīng)廢棄了onActivityResult
    2022-09-09
  • 基于RxJava框架實現(xiàn)獲取驗證碼的輔助類

    基于RxJava框架實現(xiàn)獲取驗證碼的輔助類

    這篇文章主要為大家詳細(xì)介紹了基于RxJava框架實現(xiàn)獲取驗證碼的輔助類,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Android中使用PagerSlidingTabStrip實現(xiàn)導(dǎo)航標(biāo)題的示例

    Android中使用PagerSlidingTabStrip實現(xiàn)導(dǎo)航標(biāo)題的示例

    本篇文章主要介紹了Android中使用PagerSlidingTabStrip實現(xiàn)導(dǎo)航標(biāo)題的示例,具有一定的參考價值,有興趣的可以了解一下。
    2017-01-01
  • android 分辨率適配的方法

    android 分辨率適配的方法

    先和大家分享下,這個方法不能說萬能的,但是最起碼它解決了分辨率跟密集度的關(guān)系,但是也引來一個問題,就是布局會因為圖片資源小而失真,本文將詳細(xì)介紹android 分辨率適配的方法,需要的朋友可以參考下
    2012-11-11

最新評論