編寫自定義View并發(fā)布到JCenter

很多開(kāi)發(fā)者開(kāi)發(fā)了多個(gè)項(xiàng)目之后,都會(huì)積累一些自定義的View或者工具類身害,每次開(kāi)始一個(gè)新項(xiàng)目的時(shí)候一般都是一個(gè)包復(fù)制過(guò)去苍日,其實(shí)我們可以將自己常用的一些東西封裝起來(lái)封裝到Library里面把敞,然后將他發(fā)布到j(luò)Center圾叼,以后在做項(xiàng)目直接在gradle中添加依賴就可以了朱庆。

本文我們來(lái)編寫一個(gè)自定義View盛泡,并將它發(fā)布到JCenter。

1 自定義View

先來(lái)看下目標(biāo)View的運(yùn)行結(jié)果娱颊。

很簡(jiǎn)單的一個(gè)View傲诵,三個(gè)圓角方形,依次增大縮小并改變透明度箱硕,如果你看著眼熟的話拴竹,可能你經(jīng)常看Tumblr剧罩,恩栓拜,我就是cos的Tumblrloading,經(jīng)常逛Tumblr覺(jué)得UI設(shè)計(jì)還是挺好的惠昔,至于我逛Tumblr都看些啥幕与,老司機(jī)們都懂的。

1.1 添加Library

首先我們來(lái)創(chuàng)建項(xiàng)目舰罚,new Project命名為BlockLoading纽门,包名最好加上.sample做后綴,即xxx.xxx.blockloading.sample這樣的結(jié)構(gòu)营罢。

接著給項(xiàng)目添加Library赏陵,File -> New -> New Module饼齿,如圖

選擇Android Library -> Next

Library名稱為BlockLoading,包名xxx.xxx.blockloading蝙搔,所以你現(xiàn)在理解為什么開(kāi)始創(chuàng)建項(xiàng)目的時(shí)候包名后面要添加后綴了吧缕溉,因?yàn)檫@個(gè)Library才是我們要發(fā)布的內(nèi)容。

目前為止項(xiàng)目就創(chuàng)建好了吃型,我將app改名為sample证鸥,BlockLoading改名為library,你知道什么意思就好勤晚,不必改成一樣的枉层。

在library下添加一個(gè)BlockLoading文件,內(nèi)容如下:

package com.axiba.blockloading;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class BlockLoading extends View {

    public static final String TAG = BlockLoading.class.getSimpleName();

    public BlockLoading(Context context) {
        super(context);
    }

    public BlockLoading(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BlockLoading(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
}

修改sample項(xiàng)目的build.gradle文件赐写,在dependencies中添加compile project(':library')鸟蜡,例如:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':library')
    compile 'com.android.support:appcompat-v7:23.4.0'
}

現(xiàn)在我們可以在sample中引用library的文件了,在activity_main.xml中引用BlockLoading:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <com.axiba.blockloading.BlockLoading
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

當(dāng)然這個(gè)控件什么都沒(méi)有寫挺邀,所以什么也不會(huì)展示的揉忘,只是構(gòu)建好了項(xiàng)目的框架而已。

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step1

1.2 繪制初始狀態(tài)的Block

先分析下目標(biāo)View端铛,三個(gè)圓角滑塊泣矛,慢慢長(zhǎng)高,由比較透明變的沒(méi)有那么透明禾蚕。那么我們先來(lái)繪制三個(gè)初始狀態(tài)的Block您朽。

由于目標(biāo)view是三個(gè)方塊,也就是說(shuō)第二個(gè)方塊的中心應(yīng)該和view的中心重合夕膀,所以我們從中心點(diǎn)出發(fā)虚倒,分別找到三個(gè)滑塊的left和top坐標(biāo)。

中間滑塊的坐標(biāo)為:

block2Top = height / 2 - blockHeight / 2;
block2Left = width / 2 - blockWidth / 2;

三個(gè)方塊目前都是靜態(tài)的产舞,所以top坐標(biāo)都一樣魂奥。由圖分析我們可以分別得到另外兩個(gè)方塊的坐標(biāo):

block1Left = block2Left - blockSpace - blockWidth;
block3Left = block2Left + blockSpace + blockWidth;

得到位置關(guān)系后我們現(xiàn)在可以繪制三個(gè)方塊了。

定義以下變量:

    //畫筆
    private Paint paint;

    //默認(rèn)模塊顏色
    private int defaultColor = Color.rgb(200, 200, 200);

    //繪制區(qū)域的寬高
    private int width;
    private int height;

    //方塊的間距
    private float blockSpace;

    //方塊的寬和高
    private float blockWidth;
    private float blockHeight;

    //方塊的頂坐標(biāo)
    private float blockTop;

    //方塊的左坐標(biāo)
    private float block1Left;
    private float block2Left;
    private float block3Left;

添加一個(gè)初始化方法init代碼如下:

    //初始化參數(shù)
    private void init(){

        //創(chuàng)建畫筆
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //設(shè)置畫筆顏色
        paint.setColor(defaultColor);
        //設(shè)置透明度
        paint.setAlpha(100);

        width = getMeasuredWidth();
        height = getMeasuredHeight();

        blockSpace = 25;
        blockWidth = 100;
        blockHeight = 110;

        blockTop = (height - blockHeight) / 2;

        block2Left = (width - blockWidth) / 2;
        block1Left = block2Left - blockSpace - blockWidth;
        block3Left = block2Left + blockSpace + blockWidth;
    }

這里暫時(shí)先將參數(shù)寫死易猫,那么調(diào)用的時(shí)候最好使用match_parent模式來(lái)調(diào)用view耻煤。

init方法應(yīng)該在哪調(diào)用呢?
由于在init中我們要獲取view的width和height准颓,那么在構(gòu)造方法用調(diào)用肯定是不行的哈蝇,因?yàn)檫@時(shí)候控件還沒(méi)有經(jīng)過(guò)measure,沒(méi)有辦法獲取控件的width和height攘已。

一個(gè)View的繪制要經(jīng)過(guò)measure -> layout -> draw炮赦。在measure之后我們就能獲取view的width和height了,其實(shí)在onMeasure方法之后就已經(jīng)能夠準(zhǔn)確獲取view的width和height了样勃,那么init方法可以在onLayout中調(diào)用也可以在onDraw中調(diào)用吠勘,不過(guò)初始化方法更像是在給這個(gè)view做布局性芬,那么我們就在onLayout中調(diào)用,如果在onDraw中調(diào)用的話剧防,可以引用一個(gè)變量來(lái)標(biāo)注是否已經(jīng)初始化植锉,以避免重復(fù)調(diào)用init

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    init();
}

然后我們要在onDraw中繪制方塊峭拘,使用canvas.drawRoundRect可以來(lái)繪制一個(gè)圓角方塊俊庇,不過(guò)要21版本以上才支持,由于我們只是演示鸡挠,所以暫時(shí)使用這個(gè)方法辉饱。代碼如下:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {

        //繪制方塊
        canvas.drawRoundRect(block1Left, blockTop, block1Left + blockWidth, blockTop + blockHeight, 5, 5, paint);
        canvas.drawRoundRect(block2Left, blockTop, block2Left + blockWidth, blockTop + blockHeight, 5, 5, paint);
        canvas.drawRoundRect(block3Left, blockTop, block3Left + blockWidth, blockTop + blockHeight, 5, 5, paint);
    }

運(yùn)行結(jié)果如下:

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step2

1.3 按照比例分配尺寸

現(xiàn)在的尺寸是寫死的,實(shí)際當(dāng)中肯定不可能是這樣的拣展,首先我們要分配一下寬高的比例鞋囊,參考下圖:

其中黃色部分是padding的部分,紅色的部分是我們繪制的區(qū)域瞎惫,那么width和height需要減掉padding的部分。

width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();

按照?qǐng)D上的分配译株,初始化相應(yīng)的變量如下:

blockSpace = width * 0.05f;
blockWidth = width * 0.2f;
blockMinHeight = blockWidth * 1.1f;
blockMinHeight = blockWidth * 1.5f;

blockHeight = blockMinHeight;

當(dāng)然比例你可以自由分配瓜喇。

接下來(lái)為了讓wrap_content生效,我們要給控件添加一個(gè)最小的寬度和最小的高度:

private static final int DEFAULT_MIN_WIDTH = 200;   //默認(rèn)寬度
private static final int DEFAULT_MIN_HEIGHT = 100;  //默認(rèn)高度

并重寫onMeasure方法

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getMode(heightMeasureSpec);

        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_MIN_WIDTH, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, DEFAULT_MIN_HEIGHT);
        }
    }

這段代碼解釋起來(lái)就是如果寬或者高定義為wrap_content歉糜,那么就將對(duì)應(yīng)的值設(shè)為我們默認(rèn)的最小值乘寒,單位是px。如果你想具體了解measure的過(guò)程匪补,推薦看《Android開(kāi)發(fā)藝術(shù)探索》這本書伞辛。

現(xiàn)在我們來(lái)修改layout文件,將width和height修改為wrap_content模式夯缺,并運(yùn)行蚤氏,可以得到下圖的效果:

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step3

1.4 讓方塊動(dòng)起來(lái)

讓方塊動(dòng)起來(lái)其實(shí)就是更改他的高度和透明度,重新繪制踊兜。

目標(biāo)效果是從小變大竿滨,到最大之后在變小的反復(fù)過(guò)程,那么我需要兩個(gè)常亮分別表示變大和變小兩個(gè)階段捏境。然后使用變量標(biāo)記block的當(dāng)前狀態(tài)于游。

private static final int BLOCK_STATE_IN = 1;       //增加
private static final int BLOCK_STATE_DE = 2;       //減小

//狀態(tài) 增加或減小
private int blockState;

定義一個(gè)常量,表示由最小到最大經(jīng)歷的幀數(shù)垫言,并定義一個(gè)變量來(lái)記錄每次block高度的變化量贰剥,最后再定義一個(gè)變量來(lái)記錄當(dāng)前的幀數(shù)。

private static final int STEP_NUM = 15;    //總幀數(shù)筷频,從0開(kāi)始為第一幀
private float blockStepHeight;  //每次變化的高度
private int blockStep;  //當(dāng)前幀

blockStepHeight可以在得到最大高度和最小高度后初始化:

//初始化參數(shù)
private void init(){

    ......

    //初始化方塊起始狀態(tài)為變大
    blockState = BLOCK_STATE_IN;

    //初始化每一幀height變化量
    blockStepHeight = (blockMaxHeight - blockMinHeight) / STEP_NUM;

    blockStep = 0;
}

最后來(lái)修改onDraw方法蚌成,內(nèi)容如下:

protected void onDraw(Canvas canvas) {

    if (blockState == BLOCK_STATE_IN) {
        //如果是變大狀態(tài)前痘,幀數(shù)+1
        blockStep++;
    } else {
        //如果是變小狀態(tài),幀數(shù)-1
        blockStep--;
    }

    //根據(jù)當(dāng)前幀數(shù)獲得高度
    blockHeight = blockMinHeight + blockStep * blockStepHeight;
    //獲取頂點(diǎn)坐標(biāo)
    blockTop = (height - blockHeight) / 2;
    
    //繪制方塊
    canvas.drawRoundRect(block1Left, blockTop, block1Left + blockWidth, blockTop + blockHeight, 5, 5, paint);
    canvas.drawRoundRect(block2Left, blockTop, block2Left + blockWidth, blockTop + blockHeight, 5, 5, paint);
    canvas.drawRoundRect(block3Left, blockTop, block3Left + blockWidth, blockTop + blockHeight, 5, 5, paint);

    if (blockStep >= STEP_NUM) {
        //如果幀數(shù)已經(jīng)是最后一幀笑陈,狀態(tài)改為變小狀態(tài)
        blockState = BLOCK_STATE_DE;
    } else if(blockStep <= 0){
        //如果幀數(shù)已經(jīng)是第一幀际度,狀態(tài)改為變大狀態(tài)
        blockState = BLOCK_STATE_IN;
    }

    //觸動(dòng)刷新
    postInvalidate();

}

代碼比較簡(jiǎn)單,注釋應(yīng)該也能看懂涵妥,就不多做解釋了乖菱。為了運(yùn)行效果更好沙合,還是將view的width和height改為match_parent孽惰。運(yùn)行結(jié)果如下:

可以看到三個(gè)block一起動(dòng)了起來(lái)少欺。

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step4

1.5 最后的封裝

最后要做的事其實(shí)特別簡(jiǎn)單或听,我們只要給三個(gè)block初始化不同的step就可以實(shí)現(xiàn)目標(biāo)的效果阁危。至于透明度的變化和高度的變化道理是一樣的旁仿,最后添加了一個(gè)小功能俭缓,就是為block設(shè)置顏色聋溜,這里就直接給出最后封裝好的代碼锯厢,供大家參考皮官。

package com.axiba.blockloading;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by axiba on 2016/11/17.
 */

public class BlockLoading extends View {

    public static final String TAG = BlockLoading.class.getSimpleName();

    //畫筆
    private Paint paint;

    //默認(rèn)模塊顏色
    private int defaultColor = Color.rgb(200, 200, 200);

    //block顏色
    private int blockColor;

    //繪制區(qū)域的寬高
    private int width;
    private int height;

    private static final int DEFAULT_MIN_WIDTH = 200;   //默認(rèn)寬度
    private static final int DEFAULT_MIN_HEIGHT = 100;  //默認(rèn)高度

    private static final int MIN_ALPHA = 100;      //透明度最小值
    private static final int MAX_ALPHA = 200;      //透明度最大值

    private static final int BLOCK_STATE_IN = 1;       //增加
    private static final int BLOCK_STATE_DE = 2;       //減小

    private static final int STEP_NUM = 15;    //總幀數(shù),從0開(kāi)始為第一幀
    private float blockStepHeight;  //每次變化的高度
    private int blockStepAlpha;     //每次透明度變化的量
//    private int blockStep;  //當(dāng)前幀

    //當(dāng)前幀
    private int block1Step;
    private int block2Step;
    private int block3Step;
    private int[] blocksStep;

    //方塊的間距
    private float blockSpace;

    //方塊的寬和高
    private float blockWidth;
//    private float blockHeight;

    private float blockMinHeight;   //最小的高度
    private float blockMaxHeight;   //最大的高度

//    //方塊的頂坐標(biāo)
//    private float blockTop;

    //方塊的左坐標(biāo)
    private float block1Left;
    private float block2Left;
    private float block3Left;
    private float[] blocksLeft;

    //狀態(tài) 增加或減小
//    private int blockState;
    private int block1State;
    private int block2State;
    private int block3State;
    private int[] blocksState;

    //圓角半徑
    private float r;

    public BlockLoading(Context context) {
        super(context);
    }

    public BlockLoading(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BlockLoading(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.loading);
        //獲取block_color
        blockColor = a.getColor(R.styleable.loading_block_color, defaultColor);
    }

    //初始化參數(shù)
    private void init(){

        //創(chuàng)建畫筆
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //設(shè)置畫筆顏色
//        paint.setColor(defaultColor);
        paint.setColor(blockColor);
        //設(shè)置透明度
        paint.setAlpha(100);

        width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
        height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();

        //為了保持比例
        if ((width / 2) > height) {
            width = height * 2;
        }

//        blockSpace = 25;
//        blockWidth = 100;
//        blockHeight = 110;
        blockSpace = width * 0.05f;
        blockWidth = width * 0.2f;
        blockMinHeight = blockWidth * 1.1f;
        blockMaxHeight = blockWidth * 1.5f;

        block2Left = (width - blockWidth) / 2;
        block1Left = block2Left - blockSpace - blockWidth;
        block3Left = block2Left + blockSpace + blockWidth;

        //初始化方塊起始狀態(tài)為變大
//        blockState = BLOCK_STATE_IN;
        block1State = BLOCK_STATE_IN;
        block2State = BLOCK_STATE_IN;
        block3State = BLOCK_STATE_IN;

        //初始化每一幀height變化量
        blockStepHeight = (blockMaxHeight - blockMinHeight) / STEP_NUM;
        blockStepAlpha = Math.round((MAX_ALPHA - MIN_ALPHA) / STEP_NUM);

//        blockStep = 0;
        //為每個(gè)block初始化不同的起點(diǎn)
        block1Step = 14;
        block2Step = 7;
        block3Step = 0;

        r = blockWidth / 8;

        blocksStep = new int[]{block1Step, block2Step, block3Step};
        blocksState = new int[]{block1State, block2State, block3State};
        blocksLeft = new float[]{block1Left, block2Left, block3Left};

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getMode(heightMeasureSpec);

        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(DEFAULT_MIN_WIDTH, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, DEFAULT_MIN_HEIGHT);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {

        for (int i = 0; i < 3; i++) {
            drawBlock(canvas, i);
        }

        //觸動(dòng)刷新
        postInvalidate();

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void drawBlock(Canvas canvas, int index){
        float blockTop;
        float blockLeft = blocksLeft[index];
        float blockHeight;
        int blockAlpha;

        if (blocksState[index] == BLOCK_STATE_IN) {
            //如果是變大狀態(tài)实辑,幀數(shù)+1
            blocksStep[index]++;
        } else {
            //如果是變小狀態(tài)捺氢,幀數(shù)-1
            blocksStep[index]--;
        }

        //根據(jù)當(dāng)前幀數(shù)獲得高度
        blockHeight = blockMinHeight + blocksStep[index] * blockStepHeight;

        //根據(jù)當(dāng)前幀數(shù)獲得透明度
        blockAlpha = MIN_ALPHA + blocksStep[index] * blockStepAlpha;

        //保持height值在最大值和最小值范圍之內(nèi)
        blockHeight = Math.min(blockMaxHeight, Math.max(blockMinHeight, blockHeight));

        //保持alpha值在最大值和最小值范圍之內(nèi)
        blockAlpha = Math.min(MAX_ALPHA, Math.max(MIN_ALPHA, blockAlpha));

        //獲取頂點(diǎn)坐標(biāo)
        blockTop = (height - blockHeight) / 2;

        //設(shè)置透明度
        paint.setAlpha(blockAlpha);

        //繪制方塊
        canvas.drawRoundRect(blockLeft, blockTop, blockLeft + blockWidth, blockTop + blockHeight, r, r, paint);


        // -5 是為了增加一個(gè)停頓感
        if (blocksStep[index] >= STEP_NUM) {
            //如果幀數(shù)已經(jīng)是最后一幀,狀態(tài)改為變小狀態(tài)
            blocksState[index] = BLOCK_STATE_DE;
        } else if(blocksStep[index] <= 0 - 5){
            //如果幀數(shù)已經(jīng)是第一幀剪撬,狀態(tài)改為變大狀態(tài)
            blocksState[index] = BLOCK_STATE_IN;
        }
    }
}

別忘了添加attr.xml文件摄乒,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="loading">
        <attr name="block_color" format="color"/>
    </declare-styleable>
</resources>

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step5

2 發(fā)布到Maven

發(fā)布組件的過(guò)程大概如下:

  1. 生成Maven需要的pom文件
  2. 打包源碼和doc
  3. 上傳到Bintray
  4. 發(fā)布到JCenter

2.1 添加Maven插件和Bintray插件

編輯項(xiàng)目的根目錄下的build.gradle

buildscript {
    ......
    dependencies {
        .......
        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
    }
}

2.2 應(yīng)用插件

修改庫(kù)模塊下的build.gradle,添加如下代碼即可使用上面的插件

apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'

這兩個(gè)插件一個(gè)幫你生成pom文件残黑,一個(gè)將你的打包文件上傳到bintray馍佑。

2.3 添加pom文件相關(guān)內(nèi)容

group = 'com.axiba.blockloading'
version = '1.0'

在maven中引用一個(gè)插件的代碼是這樣的:

<dependency>
  <groupId>com.axiba.blockloading</groupId>
  <artifactId>library</artifactId>
  <version>1.0</version>
  <type>pom</type>
</dependency>

同樣的插件在gradle中引用是這樣的:

compile 'com.axiba.blockloading:library:1.0'

也就是groupId:artifactId:version的形式。
那么我們指定了gruopIdversion梨水,artifactId就是項(xiàng)目的名稱拭荤,這里是library

接著指定一些pom相關(guān)的內(nèi)容:

def siteUrl = 'https://github.com/tough1985/BlockLoading'
def gitUrl = 'https://github.com/tough1985/BlockLoading.git'

//用戶生成Maven的pom文件
install {
    repositories.mavenInstaller {
        pom {
            project {
                packaging 'aar'
                name 'BlockLoading'
                url siteUrl

                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }

                developers {
                    developer {
                        id 'axiba'
                        name 'axiba'
                        email '66903041@qq.com'
                    }
                }

                scm {
                    connection gitUrl
                    developerConnection gitUrl
                    url siteUrl
                }
            }
        }
    }
}

2.4 生成源文件JAR和Javadoc JAR

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

現(xiàn)在你可以在右側(cè)的Gradle側(cè)邊欄中找到:library -> Tasks -> other -> install疫诽,運(yùn)行成功后可以在library項(xiàng)目下的build文件夾下看到生成的相關(guān)文件穷劈。

2.5 使用Bintray

首先到Bintray官網(wǎng)上注冊(cè)個(gè)用戶,直接用github的賬號(hào)就行踊沸。

點(diǎn)擊這里添加一個(gè)倉(cāng)庫(kù)歇终。

選擇public;倉(cāng)庫(kù)名稱你可以隨意逼龟,但是要記住名字评凝,后面要用;type選擇Maven腺律。

在library目錄下添加一個(gè)文件名為bintrary.properties奕短。
并在.gitignore中添加bintray.properties宜肉。

bintrary.properties的內(nèi)容如下:

bintray_user=tough1985
bintray_key=you_bintray_key
bintray_userOrg=axiba
bintray_repo=maven

這4個(gè)值在哪拿呢?看圖翎碑!

repo就是創(chuàng)建倉(cāng)庫(kù)時(shí)的倉(cāng)庫(kù)名稱谬返,點(diǎn)擊EditProfile


user和userOrg

key

最后在build.gradle文件中添加代碼:


artifacts {
    archives javadocJar
    archives sourcesJar
}

//加載配置文件
def bintrayProperties = new Properties()
bintrayProperties.load(new FileInputStream(file("bintray.properties")))

bintray {
    user = bintrayProperties['bintray_user']
    key = bintrayProperties['bintray_key']
    configurations = ['archives']
    pkg {
        userOrg = bintrayProperties['bintray_userOrg']
        repo = bintrayProperties['bintray_repo']
        name = 'com.axiba.blockloading'
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        licenses = ['Apache-2.0']
        publish = true
    }
}

運(yùn)行下圖的Task


運(yùn)行成功之后,到Bintray上你的倉(cāng)庫(kù)中可以找到對(duì)應(yīng)的項(xiàng)目日杈。

現(xiàn)在你可以新建一個(gè)項(xiàng)目遣铝,通過(guò)maven來(lái)引入這個(gè)項(xiàng)目了。

編輯根項(xiàng)目的build.gradle

allprojects {
    repositories {
        jcenter()
        maven {
            url 'https://axiba.bintray.com/maven'  //你的Bintray上的manve地址
        }
    }
}

在app中的build.gradle添加依賴:

compile 'com.axiba.blockloading:library:1.0'

2.6 同步到JCenter

想要同步到JCenter的話只要在Bintray中點(diǎn)擊個(gè)按鈕并編輯下內(nèi)容就可以了莉擒,看圖酿炸。


然后輸入一些項(xiàng)目的相關(guān)描述就可以了。JCenter是需要審核的涨冀,審核好了你就不用在引用自己的倉(cāng)庫(kù)了填硕。

如需查看項(xiàng)目代碼 --> 代碼地址:

https://github.com/tough1985/BlockLoading

選擇Tag -> step6

結(jié)語(yǔ)

本文比較簡(jiǎn)單,并沒(méi)有什么技術(shù)難度鹿鳖,相關(guān)的內(nèi)容其實(shí)網(wǎng)上也有很多扁眯,不過(guò)我還是踩到了坑。如果你在運(yùn)行g(shù)radle相關(guān)task出錯(cuò)的話翅帜,我建議你使用命令行的方式運(yùn)行task恋拍,可以看到清晰的出錯(cuò)原因,方便解決問(wèn)題藕甩。還有就是可以運(yùn)行一下clean這個(gè)task來(lái)做一下清理在去運(yùn)行其他的task。

利用這個(gè)功能可以封裝一些自己常用的工具類周荐,application狭莱,activity,fragment等相關(guān)內(nèi)容概作,也可以自己封裝一些mvp的基類腋妙,方便快速開(kāi)發(fā)新項(xiàng)目,讓你在新項(xiàng)目開(kāi)發(fā)的過(guò)程中把精力集中在業(yè)務(wù)邏輯上讯榕,避免重復(fù)的搭建相關(guān)框架骤素。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市愚屁,隨后出現(xiàn)的幾起案子济竹,更是在濱河造成了極大的恐慌,老刑警劉巖霎槐,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件送浊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丘跌,警方通過(guò)查閱死者的電腦和手機(jī)袭景,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門唁桩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人耸棒,你說(shuō)我怎么就攤上這事荒澡。” “怎么了与殃?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵单山,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我奈籽,道長(zhǎng)饥侵,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任衣屏,我火速辦了婚禮躏升,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狼忱。我一直安慰自己膨疏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布钻弄。 她就那樣靜靜地躺著佃却,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窘俺。 梳的紋絲不亂的頭發(fā)上饲帅,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音瘤泪,去河邊找鬼灶泵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛对途,可吹牛的內(nèi)容都是我干的赦邻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼实檀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惶洲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起膳犹,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤恬吕,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后须床,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體币呵,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了余赢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芯义。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妻柒,靈堂內(nèi)的尸體忽然破棺而出扛拨,到底是詐尸還是另有隱情,我是刑警寧澤举塔,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布绑警,位于F島的核電站,受9級(jí)特大地震影響央渣,放射性物質(zhì)發(fā)生泄漏计盒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一芽丹、第九天 我趴在偏房一處隱蔽的房頂上張望北启。 院中可真熱鬧,春花似錦拔第、人聲如沸咕村。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)懈涛。三九已至,卻和暖如春泳猬,著一層夾襖步出監(jiān)牢的瞬間批钠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工得封, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留埋心,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓呛每,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坡氯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晨横,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容