Android帶你實現門票佈局效果

Songlcy發表於2016-07-27

今天帶給大家一個門票佈局的效果。直接看圖吧:

上圖展示了一個門票列表的介面,可以發現每個Item的四個角都是凹下去的。並且圖片左邊上下兩個角也是凹下去的。我們該如何實現這種效果呢?

有朋友可能會說UI肯定會給一個這樣的背景圖片的。嗯,使用這樣的圖片肯定沒問題,缺點就是加在多了佔據記憶體而已。可是Photo的左上和左下也是要這樣的圓角哇。該怎麼辦呢?

基於這種需求,我們可以變換一種方式來實現。讓UI給我們每個角的半徑,我們自己來畫出來就OK了。


我們今天要實現的效果是不使用任何圖片,完全自定義佈局和圖片來實現這樣的效果。

實現思路:

(1)自定義一個佈局,繼承自LinearLayout,使用Paint根據半徑在四個角畫四個圓,背景為白色。

(2)自定義圖片控制元件,繼承自ImageView,同樣使用Paint根據半徑在左上角和左下角畫圓,背景為白色。

思路很清楚,就是利用了畫圓的效果在視覺上給人一種凹角的感覺。下面看核心程式碼:

自定義LinearLayout:

/**
 * View的大小發生改變時並且在onFinishInflate方法後被回撥
 * @param w
 * @param h
 * @param oldw
 * @param oldh
 */
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    //獲取佈局的寬高
    this.layoutWidth = w;
    this.layoutHeight = h;

}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawCircle(0,0,radius,paint);
    canvas.drawCircle(0,layoutHeight,radius,paint);
    canvas.drawCircle(layoutWidth,0,radius,paint);
    canvas.drawCircle(layoutWidth,layoutHeight,radius,paint);
}
自定義IamegView:

/**
 * View的大小發生改變時並且在onFinishInflate方法後被回撥
 * @param w
 * @param h
 * @param oldw
 * @param oldh
 */
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    //獲取佈局的寬高
    this.layoutWidth = w;
    this.layoutHeight = h;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawCircle(0,0,radius,paint);
    canvas.drawCircle(0, layoutHeight, radius, paint);
}

圓的半徑我們通過自定義屬性來實現:

<declare-styleable name="TLayout">
    <attr name="radius" format="dimension" />
</declare-styleable>

然後在建構函式中獲取即可:

public TLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.TLayout,defStyleAttr,0);
    int num = ta.getIndexCount();
    for (int i = 0; i < num; i++) {
        int attr = ta.getIndex(i);
        switch (attr) {
            case R.styleable.TLayout_radius:
                radius = ta.getDimensionPixelSize(attr,
                        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,5,getResources().getDisplayMetrics()));
                break;
            default:
                break;
        }
    }
    ta.recycle();
    initPaint();
}
上面程式碼使用了for迴圈的方式來獲取自定義的屬性值,這種方式適合屬性多的場景,如果自定義屬性值比較少,那麼可以使用下面這個方法來獲取:

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TLayout, defStyleAttr, 0);
radius = ta.getDimensionPixelSize(R.styleable.TLayout_radius,
        (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,5,getResources().getDisplayMetrics()));
ta.recycle();

ok,來看下效果圖:

好啦,今天的介紹就到這裡啦,有問題的朋友給我留言。

原始碼下載

相關文章