亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在Android中利用View實現一個垂直時間軸布局

發布時間:2020-11-26 17:10:26 來源:億速云 閱讀:166 作者:Leah 欄目:移動開發

這篇文章將為大家詳細講解有關如何在Android中利用View實現一個垂直時間軸布局,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

時間軸,顧名思義就是將發生的事件按照時間順序羅列起來,給用戶帶來一種更加直觀的體驗。

分析

實現這個最常用的一個方法就是用ListView,我這里用繼承LinearLayout的方式來實現。首先定義了一些自定義屬性:

attrs.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
  <declare-styleable name="TimelineLayout"> 
    <!--時間軸左偏移值--> 
    <attr name="line_margin_left" format="dimension"/> 
    <!--時間軸上偏移值--> 
    <attr name="line_margin_top" format="dimension"/> 
    <!--線寬--> 
    <attr name="line_stroke_width" format="dimension"/> 
    <!--線的顏色--> 
    <attr name="line_color" format="color"/> 
    <!--點的大小--> 
    <attr name="point_size" format="dimension"/> 
    <!--點的顏色--> 
    <attr name="point_color" format="color"/> 
    <!--圖標--> 
    <attr name="icon_src" format="reference"/> 
  </declare-styleable> 
</resources>

TimelineLayout.java

package com.jackie.timeline; 
 
import android.content.Context; 
import android.content.res.TypedArray; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.drawable.BitmapDrawable; 
import android.support.annotation.Nullable; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.LinearLayout; 
 
/** 
 * Created by Jackie on 2017/3/8. 
 * 時間軸控件 
 */ 
 
public class TimelineLayout extends LinearLayout { 
  private Context mContext; 
 
  private int mLineMarginLeft; 
  private int mLineMarginTop; 
  private int mLineStrokeWidth; 
  private int mLineColor;; 
  private int mPointSize; 
  private int mPointColor; 
  private Bitmap mIcon; 
 
  private Paint mLinePaint; //線的畫筆 
  private Paint mPointPaint; //點的畫筆 
   
 
  //第一個點的位置 
  private int mFirstX; 
  private int mFirstY; 
  //最后一個圖標的位置 
  private int mLastX; 
  private int mLastY; 
 
  public TimelineLayout(Context context) { 
    this(context, null); 
  } 
 
  public TimelineLayout(Context context, @Nullable AttributeSet attrs) { 
    this(context, attrs, 0); 
  } 
 
  public TimelineLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TimelineLayout); 
    mLineMarginLeft = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_margin_left, 10); 
    mLineMarginTop = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_margin_top, 0); 
    mLineStrokeWidth = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_line_stroke_width, 2); 
    mLineColor = ta.getColor(R.styleable.TimelineLayout_line_color, 0xff3dd1a5); 
    mPointSize = ta.getDimensionPixelSize(R.styleable.TimelineLayout_point_size, 8); 
    mPointColor = ta.getDimensionPixelOffset(R.styleable.TimelineLayout_point_color, 0xff3dd1a5); 
 
    int iconRes = ta.getResourceId(R.styleable.TimelineLayout_icon_src, R.drawable.ic_ok); 
    BitmapDrawable drawable = (BitmapDrawable) context.getResources().getDrawable(iconRes); 
    if (drawable != null) { 
      mIcon = drawable.getBitmap(); 
    } 
 
    ta.recycle(); 
 
    setWillNotDraw(false); 
    initView(context); 
  } 
 
  private void initView(Context context) { 
    this.mContext = context; 
 
    mLinePaint = new Paint(); 
    mLinePaint.setAntiAlias(true); 
    mLinePaint.setDither(true); 
    mLinePaint.setColor(mLineColor); 
    mLinePaint.setStrokeWidth(mLineStrokeWidth); 
    mLinePaint.setStyle(Paint.Style.FILL_AND_STROKE); 
 
    mPointPaint = new Paint(); 
    mPointPaint.setAntiAlias(true); 
    mPointPaint.setDither(true); 
    mPointPaint.setColor(mPointColor); 
    mPointPaint.setStyle(Paint.Style.FILL); 
  } 
 
  @Override 
  protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
     
    drawTimeline(canvas); 
  } 
 
  private void drawTimeline(Canvas canvas) { 
    int childCount = getChildCount(); 
 
    if (childCount > 0) { 
      if (childCount > 1) { 
        //大于1,證明至少有2個,也就是第一個和第二個之間連成線,第一個和最后一個分別有點和icon 
        drawFirstPoint(canvas); 
        drawLastIcon(canvas); 
        drawBetweenLine(canvas); 
      } else if (childCount == 1) { 
        drawFirstPoint(canvas); 
      } 
    } 
  } 
 
  private void drawFirstPoint(Canvas canvas) { 
    View child = getChildAt(0); 
    if (child != null) { 
      int top = child.getTop(); 
      mFirstX = mLineMarginLeft; 
      mFirstY = top + child.getPaddingTop() + mLineMarginTop; 
 
      //畫圓 
      canvas.drawCircle(mFirstX, mFirstY, mPointSize, mPointPaint); 
    } 
  } 
 
  private void drawLastIcon(Canvas canvas) { 
    View child = getChildAt(getChildCount() - 1); 
    if (child != null) { 
      int top = child.getTop(); 
      mLastX = mLineMarginLeft; 
      mLastY = top + child.getPaddingTop() + mLineMarginTop; 
 
      //畫圖 
      canvas.drawBitmap(mIcon, mLastX - (mIcon.getWidth() >> 1), mLastY, null); 
    } 
  } 
 
  private void drawBetweenLine(Canvas canvas) { 
    //從開始的點到最后的圖標之間,畫一條線 
    canvas.drawLine(mFirstX, mFirstY, mLastX, mLastY, mLinePaint); 
    for (int i = 0; i < getChildCount() - 1; i++) { 
      //畫圓 
      int top = getChildAt(i).getTop(); 
      int y = top + getChildAt(i).getPaddingTop() + mLineMarginTop; 
      canvas.drawCircle(mFirstX, y, mPointSize, mPointPaint); 
    } 
  } 
 
  public int getLineMarginLeft() { 
    return mLineMarginLeft; 
  } 
 
  public void setLineMarginLeft(int lineMarginLeft) { 
    this.mLineMarginLeft = lineMarginLeft; 
    invalidate(); 
  } 
}

從上面的代碼可以看出,分三步繪制,首先繪制開始的實心圓,然后繪制結束的圖標,然后在開始和結束之間先繪制一條線,然后在線上在繪制每個步驟的實心圓。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:app="http://schemas.android.com/apk/res-auto" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:orientation="vertical"> 
 
  <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="50dp" 
    android:weightSum="2"> 
 
    <Button 
      android:id="@+id/add_item" 
      android:layout_width="0dp" 
      android:layout_height="match_parent" 
      android:layout_weight="1" 
      android:text="add"/> 
 
    <Button 
      android:id="@+id/sub_item" 
      android:layout_width="0dp" 
      android:layout_height="match_parent" 
      android:layout_weight="1" 
      android:text="sub"/> 
  </LinearLayout> 
 
  <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    android:weightSum="2"> 
 
    <Button 
      android:id="@+id/add_margin" 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:text="+"/> 
 
    <Button 
      android:id="@+id/sub_margin" 
      android:layout_width="0dp" 
      android:layout_weight="1" 
      android:layout_height="wrap_content" 
      android:text="-"/> 
  </LinearLayout> 
 
  <TextView 
    android:id="@+id/current_margin" 
    android:layout_width="match_parent" 
    android:layout_height="40dp" 
    android:gravity="center" 
    android:text="current line margin left is 25dp"/> 
 
  <ScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:scrollbars="none"> 
 
    <com.jackie.timeline.TimelineLayout 
      android:id="@+id/timeline_layout" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      app:line_margin_left="25dp" 
      app:line_margin_top="8dp" 
      android:orientation="vertical" 
      android:background="@android:color/white"> 
    </com.jackie.timeline.TimelineLayout> 
  </ScrollView> 
</LinearLayout>

MainActivity.java

package com.jackie.timeline; 
 
import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener { 
  private Button addItemButton; 
  private Button subItemButton; 
  private Button addMarginButton; 
  private Button subMarginButton; 
  private TextView mCurrentMargin; 
 
  private TimelineLayout mTimelineLayout; 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
 
    initView(); 
  } 
 
  private void initView() { 
    addItemButton = (Button) findViewById(R.id.add_item); 
    subItemButton = (Button) findViewById(R.id.sub_item); 
    addMarginButton= (Button) findViewById(R.id.add_margin); 
    subMarginButton= (Button) findViewById(R.id.sub_margin); 
    mCurrentMargin= (TextView) findViewById(R.id.current_margin); 
    mTimelineLayout = (TimelineLayout) findViewById(R.id.timeline_layout); 
 
    addItemButton.setOnClickListener(this); 
    subItemButton.setOnClickListener(this); 
    addMarginButton.setOnClickListener(this); 
    subMarginButton.setOnClickListener(this); 
  } 
 
  private int index = 0; 
  private void addItem() { 
    View view = LayoutInflater.from(this).inflate(R.layout.item_timeline, mTimelineLayout, false); 
    ((TextView) view.findViewById(R.id.tv_action)).setText("步驟" + index); 
    ((TextView) view.findViewById(R.id.tv_action_time)).setText("2017年3月8日16:55:04"); 
    ((TextView) view.findViewById(R.id.tv_action_status)).setText("完成"); 
    mTimelineLayout.addView(view); 
    index++; 
  } 
 
  private void subItem() { 
    if (mTimelineLayout.getChildCount() > 0) { 
      mTimelineLayout.removeViews(mTimelineLayout.getChildCount() - 1, 1); 
      index--; 
    } 
  } 
 
  @Override 
  public void onClick(View v) { 
    switch (v.getId()){ 
      case R.id.add_item: 
        addItem(); 
        break; 
      case R.id.sub_item: 
        subItem(); 
        break; 
      case R.id.add_margin: 
        int currentMargin = UIHelper.pxToDip(this, mTimelineLayout.getLineMarginLeft()); 
        mTimelineLayout.setLineMarginLeft(UIHelper.dipToPx(this, ++currentMargin)); 
        mCurrentMargin.setText("current line margin left is " + currentMargin + "dp"); 
        break; 
      case R.id.sub_margin: 
        currentMargin = UIHelper.pxToDip(this, mTimelineLayout.getLineMarginLeft()); 
        mTimelineLayout.setLineMarginLeft(UIHelper.dipToPx(this, --currentMargin)); 
        mCurrentMargin.setText("current line margin left is " + currentMargin + "dp"); 
        break; 
      default: 
        break; 
    } 
  } 
}

item_timeline.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:layout_height="wrap_content" 
  android:paddingLeft="65dp" 
  android:paddingTop="20dp" 
  android:paddingRight="20dp" 
  android:paddingBottom="20dp"> 
 
  <TextView 
    android:id="@+id/tv_action" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textSize="14sp" 
    android:textColor="#1a1a1a" 
    android:text="測試一"/> 
 
  <TextView 
    android:id="@+id/tv_action_time" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textSize="12sp" 
    android:textColor="#8e8e8e" 
    android:layout_below="@id/tv_action" 
    android:layout_marginTop="10dp" 
    android:text="2017年3月8日16:49:12"/> 
 
  <TextView 
    android:id="@+id/tv_action_status" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:textSize="14sp" 
    android:textColor="#3dd1a5" 
    android:layout_alignParentRight="true" 
    android:text="完成"/> 
 
</RelativeLayout>

附上像素工具轉化的工具類:

package com.jackie.timeline; 
 
import android.content.Context; 
 
/** 
 * Created by Jackie on 2017/3/8. 
 */ 
public final class UIHelper { 
 
  private UIHelper() throws InstantiationException { 
    throw new InstantiationException("This class is not for instantiation"); 
  } 
 
  /** 
   * dip轉px 
   */ 
  public static int dipToPx(Context context, float dip) { 
    return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f); 
  } 
 
  /** 
   * px轉dip 
   */ 
  public static int pxToDip(Context context, float pxValue) { 
    final float scale = context.getResources().getDisplayMetrics().density; 
    return (int) (pxValue / scale + 0.5f); 
  } 
}

關于如何在Android中利用View實現一個垂直時間軸布局就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金坛市| 台湾省| 开鲁县| 竹北市| 航空| 高雄县| 喜德县| 南溪县| 余江县| 清水县| 民权县| 隆林| 通许县| 乌恰县| 峡江县| 壤塘县| 张家港市| 旺苍县| 临西县| 沛县| 东宁县| 阜南县| 东兰县| 富源县| 南部县| 娄底市| 招远市| 兴文县| 汝南县| 新余市| 体育| 华亭县| 湘潭市| 绥滨县| 彩票| 深水埗区| 通山县| 东丰县| 渝中区| 沅陵县| 晋州市|