Android帶有邊框的RelativeLayout、LinearLayout
阿新 • • 發佈:2018-12-09
前言
開發的時候總會遇到一些分割線,可以用一個View或者一個ImageView來繪製一條比較細的分割線,在佈局寫多了,感覺很麻煩,而且顯得程式碼不優雅,所以一個帶有邊框的ViewGroup對開發會方便很多。
1. 實現
1、自定義屬性,在 attr.xml 檔案中寫入
<!--邊框的view,可以是 RelativeLayout 或 LinearLayout -->
<declare-styleable name="BorderViewLayout">
<!--邊框的粗度-->
<attr name="borderStrokeWidth" format="float"/>
<!--邊框顏色-->
<attr name="borderColor" format="color"/>
<!--底邊邊線左邊斷開距離-->
<attr name="borderBottomLeftBreakSize" format="dimension"/>
<!--底邊邊線右邊斷開距離-->
<attr name="borderBottomRightBreakSize" format="dimension"/>
<!--是否需要上邊框-->
<attr name="needTopBorder" format="boolean"/>
<!--是否需要左右邊框-->
<attr name="needLeftAndRigtBorder" format="boolean"/>
<!--是否需要下邊框-->
<attr name="needBottomBorder" format="boolean"/>
</declare-styleable>
2、自定義控制元件,定義一個 BorderRelativeLayout 繼承自 RelativeLayout
package com.tcmain.djim.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.RelativeLayout;
import com.risen.tclibrary.R;
/**
* Created by sgll on 2018/7/17.
* 帶邊框的RelativeLayout 或 LinearLayout
*/
public class BorderRelativeLayout extends RelativeLayout {
// 預設邊框寬度, 1dp
public static final float DEFAULT_STROKE_WIDTH = 1.0f;
//畫筆
private Paint mPain;
//邊框顏色
private int mPaintColor;
//邊框粗細
private float mBorderStrokeWidth;
//底邊邊線左邊斷開距離
private int mBorderBottomLeftBreakSize;
//底邊邊線右邊斷開距離
private int mBorderBottomRightBreakSize;
//是否需要上邊框
private boolean isNeedTopBorder;
//是否需要左右邊框
private boolean isNeedLeftAndRightBorder;
//是否需要下邊框
private boolean isNeedBottomBorder;
private DisplayMetrics displayMetrics;
public BorderRelativeLayout(Context context) {
this(context, null);
}
public BorderRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BorderRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 將DIP單位預設值轉為PX
displayMetrics = context.getResources().getDisplayMetrics();
// 獲取自定義屬性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BorderViewLayout);
mPaintColor = ta.getColor(R.styleable.BorderViewLayout_borderColor, Color.GRAY);
mBorderStrokeWidth = ta.getFloat(R.styleable.BorderViewLayout_borderStrokeWidth, DEFAULT_STROKE_WIDTH);
// mBorderStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderStrokeWidth, displayMetrics);
mBorderBottomLeftBreakSize = ta.getDimensionPixelSize(R.styleable.BorderViewLayout_borderBottomLeftBreakSize, 0);
mBorderBottomLeftBreakSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderBottomLeftBreakSize, displayMetrics);
mBorderBottomRightBreakSize = ta.getDimensionPixelSize(R.styleable.BorderViewLayout_borderBottomRightBreakSize, 0);
mBorderBottomRightBreakSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderBottomRightBreakSize, displayMetrics);
isNeedTopBorder = ta.getBoolean(R.styleable.BorderViewLayout_needTopBorder, true);
isNeedLeftAndRightBorder = ta.getBoolean(R.styleable.BorderViewLayout_needLeftAndRigtBorder, false);
isNeedBottomBorder = ta.getBoolean(R.styleable.BorderViewLayout_needBottomBorder, true);
ta.recycle();
init();
}
private void init(){
mPain = new Paint();
mPain.setColor(mPaintColor);
//設定畫筆為無鋸齒
mPain.setAntiAlias(true);
//線寬
mPain.setStrokeWidth(mBorderStrokeWidth);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//畫4個邊
if(isNeedTopBorder){
canvas.drawLine(0, 0, this.getWidth(), 0, mPain);
}
if(isNeedBottomBorder){
canvas.drawLine(mBorderBottomLeftBreakSize, this.getHeight(), this.getWidth() - mBorderBottomRightBreakSize, this.getHeight(), mPain);
}
if(isNeedLeftAndRightBorder){
canvas.drawLine(0, 0, 0, this.getHeight(), mPain);
canvas.drawLine(this.getWidth(), 0, this.getWidth(), this.getHeight(), mPain);
}
}
/**
* 設定邊框顏色
* @param color 顏色
*/
public void setBorderColor(int color){
mPain.setColor(color);
invalidate();
}
/**
* 設定邊框寬度
* @param size 寬度
*/
public void setBorderStrokeWidth(float size){
mPain.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, displayMetrics));
invalidate();
}
/**
* 設定是否需要頂部邊框
* @param needtopborder boolean型別
*/
public void setNeedTopBorder(boolean needtopborder){
isNeedTopBorder = needtopborder;
invalidate();
}
/**
* 設定是否需要底部邊框
* @param needbottomborder boolean型別
*/
public void setNeedBottomBorder(boolean needbottomborder){
isNeedBottomBorder = needbottomborder;
invalidate();
}
}
3、在佈局中使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:br="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="wrap_content"
android:background="#ffffff"
android:orientation="vertical">
<!--第一行-->
<com.junweiliu.widget.BorderRelativeLayout
android:layout_width="match_parent"
android:layout_height="68dp"
android:gravity="center_vertical"
br:borderBottomLeftBreakSize="16dp"
br:borderBottomRightBreakSize="16dp"
br:borderColor="#eeeeee"
br:borderStrokeWidth="3.0">
<TextView
android:id="@+id/tv_balance_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:gravity="center"
android:text="第一行"
android:textSize="15sp"/>
<ImageView
android:id="@+id/iv_ia_prompt"
android:layout_width="14dp"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_toRightOf="@+id/tv_balance_txt"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_balance_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:layout_marginTop="24dp"
android:textColor="#333333"
android:text="第一行內容"
android:textSize="12sp"/>
</com.junweiliu.widget.BorderRelativeLayout>
<!--第二行-->
<com.junweiliu.widget.BorderRelativeLayout
android:layout_width="match_parent"
android:layout_height="67dp"
android:gravity="center_vertical"
br:borderColor="#eeeeee"
br:borderStrokeWidth="3.0"
br:needTopBorder="false">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:gravity="center"
android:text="第二行"
android:textSize="15sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:gravity="center"
android:text="第二行內容"
android:textColor="#333333"
android:textSize="12sp"/>
</com.junweiliu.widget.BorderRelativeLayout>
</LinearLayout>
</LinearLayout>
效果如下:
2. 在ListView中使用
1、帶邊框的 BorderRelativeLayout 也可使用 ListView 中,如頭部帶分割線
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:br="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<com.junweiliu.widget.BorderRelativeLayout
android:id="@+id/br_ia_detail"
android:layout_width="match_parent"
android:layout_height="72dp"
br:borderColor="#333333"
br:borderStrokeWidth="2.0"
br:needTopBorder="false"
>
<!--上邊部分-->
<TextView
android:id="@+id/tv_ia_detail_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="16sp"
android:layout_marginTop="15dp"
android:text="第一行"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_ia_detail_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginTop="15dp"
android:text="第一行內容"
android:textSize="15sp"/>
<!--下邊部分-->
<TextView
android:id="@+id/tv_ia_detail_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="15dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="12dp"
android:text="第二行"
android:textSize="11sp"/>
<TextView
android:id="@+id/tv_ia_detail_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="12dp"
android:text="第二行內容"
android:textSize="11sp"/>
</com.junweiliu.widget.BorderRelativeLayout>
</LinearLayout>
只需要在介面卡中進行判斷,就能夠新增頭部分割線了。在介面卡getView部分新增:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
// 如果是第一個位置顯示頂部邊框
BorderRelativeLayout br = (BorderRelativeLayout) convertView.findViewById(R.id.br_ia_detail);
if (0 == position) {
br.setNeedTopBorder(true);
} else {
br.setNeedTopBorder(false);
}
return convertView;
}
2、ListView 中的分割線,也可使用這個代替,只需在 item 佈局裡使用即可。
使用比較簡單,用法也比較多變,如果需要 LinearLayout,只需改變一下繼承關係就可以了。