很多開(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)目代碼 --> 代碼地址:
選擇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)目代碼 --> 代碼地址:
選擇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)目代碼 --> 代碼地址:
選擇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)目代碼 --> 代碼地址:
選擇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)目代碼 --> 代碼地址:
選擇Tag -> step5
2 發(fā)布到Maven
發(fā)布組件的過(guò)程大概如下:
- 生成Maven需要的pom文件
- 打包源碼和doc
- 上傳到Bintray
- 發(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
的形式。
那么我們指定了gruopId
和version
梨水,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)目代碼 --> 代碼地址:
選擇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)框架骤素。