Android自定义控件系列二:自定义开关按钮(一)

这一次我们将会实现一个完整纯粹的自定义控件,而不是像之前的组合控件一样,拿系统的控件来实现;计划分为三部分:自定义控件的基本部分,自定义控件的触摸事件的处理和自定义控件的自定义属性; 下面就开始第一部分的编写,本次以一个定义的开关按钮为例,下面就开始吧: 先看看效果,一个点击开关按钮,实现点击切换开关状态: 为了能够讲解清晰,还是来一些基本的介绍。 首先需要明确的就是自定义控件还是继承自View这个类,Google在View这个类里面提供了相当多的方法供我们使用,使用这些方法我们可以实现相当多的效果和功能,在这里需要用到几个主要的方法; 自定义控件的步骤、用到的主要方法: 1、首先需要定义一个类,继承自View;对于继承View的类,会需要实现至少一个构造方法;实际上这里一共有三个构造方法: **public View (Context context)**是在java代码创建视图的时候被调用(使用new的方式),如果是从xml填充的视图,就不会调用这个 **public View (Context context, AttributeSet attrs)**这个是在xml创建但是没有指定style的时候被调用 **public View (Context context, AttributeSet attrs, int defStyle)**这个是在第二个基础上添加style的时候被调用的 所以对于这里来说,如果不使用style, 我们重点关注第二个构造方法即可 2、对于任何一个控件来说,它需要显示在我们的界面上,那么肯定需要定义它的大小; 在这里Google提供了一个方法:**protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec);我们去看这个方法的内部,实际上是调用了protected final void setMeasuredDimension(int measuredWidth, int measuredHeight);**这个方法,其中第一个参数是view的宽,第二个参数是view的高,这样我们就可以设置view的宽高了,但是要注意,这样设置的单位都是像素 3、对于一个需要显示的控件来说,我们往往还需要确定它的位置: 这就要求重写onLayout方法;但是实际上这个方法在自定义view的时候使用的不多,原因是因为对于位置来说,控件只有建议权而没有决定权,决定权一般在父控件那里。 4、对于一个控件,需要显示,我们当然需要将它绘制出来,这里就需要重写onDraw方法,来将这个控件绘制出来 5、当控件状态改变的时候,我们很可能需要刷新view的显示状态,这时候就需要调用invalidate()方法,这个方法实际上会重新调用onDraw方法来重绘控件 6、在定义控件的过程中,如果需要对view设置点击事件,可以直接使用setOnClickListener方法,而不需要写view.setOnClickListener; **7、在布局文件中将这个自定义控件定义出来,注意名字要使用全类名;**而且,由于是继承自view控件,所以在xml文件中如果是view本身的属性都可以直接使用,比如:android:layout_width等等 这里比较关键的地方就在于这个onDraw方法,我们一起来看一下: **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/40736027#) [copy](http://blog.csdn.net/cyp331203/article/details/40736027#) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/505895)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/505895/fork)</span></div> </div> - <span class="comment">/**</span> - <span class="comment"> * 画view的方法,绘制当前view的内容</span> - <span class="comment"> */</span> - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onDraw(Canvas canvas) { - <span class="comment">// super.onDraw(canvas);</span> - - - Paint paint = <span class="keyword">new</span> Paint(); - <span class="comment">// 打开抗锯齿</span> - paint.setAntiAlias(<span class="keyword">true</span>); - - - <span class="comment">// 画背景</span> - canvas.drawBitmap(backgroundBitmap, <span class="number"></span>, <span class="number"></span>, paint); - <span class="comment">// 画滑块</span> - canvas.drawBitmap(slideButton, slideBtn_left, <span class="number"></span>, paint); - } </div> &nbsp; **onDraw**方法传入的参数是一个**Canvas**画布对象,这个实际上跟Java中的差不太多,我们要在画布上画画也需要一个画笔,我们这里也将其初始化出来**Paint paint = new Paint()**,同时设置了一个抗锯齿效果**paint.setAntiAlias(true)**,然后调用**drawBitmap**的方法,先后绘制了开关的背景和开关的滑块,分别入下图: ![](http://img.blog.csdn.net/20141103103403203?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3lwMzMxMjAz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) ![](http://img.blog.csdn.net/20141103103342450?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3lwMzMxMjAz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 这里要注意的一点就是,**drawBitmap(Bitmap bitmap, float left, float top, Paint paint)**方法中间的两个float类型的参数,分别代表绘制图形的左上角的x和y的坐标(原点设置在左上角),所以这里如果我们个绘制坐标都传入0,0,那么开关会处在一个关的状态,这里,我们对于滑块使用了一个变量**slideBtn_left**来设置其位置,**那么对于关闭状态,slideBtn_left的值就应该为0,对于开启状态,slideBtn_left的值就应该是backgroundBitmap(背景)的宽度减去slideButton(滑块)的宽度**; 那么这样一来,机制就比较清楚了,我们只需要在控件上设置一个点击事件,同时设置一个boolean变量代表开关的状态,当点击的时候,切换这个boolean类型的变量为true或者false,同时变化**slideButton**的值为****或者**backgroundBitmap.getWidth()-slideButton.getWidth()**,然后再调用**invalidate()**方法刷新控件,就可以实现基本的开关功能了 下面来看具体的代码,注解比较详细: 自定义控件的类MyToggleButton.java,继承自View: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/40736027#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/40736027#)</span></span> <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/505895)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/505895/fork)</span></div> </div> - <span class="keyword">package</span> com.example.togglebutton.ui; - - <span class="keyword">import</span> com.example.togglebutton.R; - - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.graphics.Bitmap; - <span class="keyword">import</span> android.graphics.BitmapFactory; - <span class="keyword">import</span> android.graphics.Canvas; - <span class="keyword">import</span> android.graphics.Paint; - <span class="keyword">import</span> android.util.AttributeSet; - <span class="keyword">import</span> android.view.View; - - <span class="comment">/*</span> - <span class="comment"> * 自定义view的几个步骤:</span> - <span class="comment"> * 1、首先需要写一个类来继承自View</span> - <span class="comment"> * 2、需要得到view的对象,那么需要重写构造方法,其中一参的构造方法用于new,二参的构造方法用于xml布局文件使用,三参的构造方法可以传入一个样式</span> - <span class="comment"> * 3、需要设置view的大小,那么需要重写onMeasure方法</span> - <span class="comment"> * 4、需要设置view的位置,那么需要重写onLayout方法,但是这个方法在自定义view的时候用的不多,原因主要在于view的位置主要是由父控件来决定</span> - <span class="comment"> * 5、需要绘制出所需要显示的view,那么需要重写onDraw方法</span> - <span class="comment"> * 6、当控件状态改变的时候,需要重绘view,那么调用invalidate();方法,这个方法实际上会重新调用onDraw方法</span> - <span class="comment"> * 7、在这其中,如果需要对view设置点击事件,可以直接调用setOnClickListener方法</span> - <span class="comment"> */</span> - - <span class="keyword">public</span> <span class="keyword">class</span> MyToggleButton <span class="keyword">extends</span> View { - - <span class="comment">/**</span> - <span class="comment"> * 开关按钮的背景</span> - <span class="comment"> */</span> - <span class="keyword">private</span> Bitmap backgroundBitmap; - <span class="comment">/**</span> - <span class="comment"> * 开关按钮的滑动部分</span> - <span class="comment"> */</span> - <span class="keyword">private</span> Bitmap slideButton; - <span class="comment">/**</span> - <span class="comment"> * 滑动按钮的左边界</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">float</span> slideBtn_left; - <span class="comment">/**</span> - <span class="comment"> * 当前开关的状态</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> currentState = <span class="keyword">false</span>; - - <span class="comment">/**</span> - <span class="comment"> * 在代码里面创建对象的时候,使用此构造方法</span> - <span class="comment"> * </span> - <span class="comment"> * @param context</span> - <span class="comment"> */</span> - <span class="keyword">public</span> MyToggleButton(Context context) { - <span class="keyword">super</span>(context); - } - - <span class="comment">/**</span> - <span class="comment"> * 在布局文件中声明的view,创建时由系统自动调用</span> - <span class="comment"> * </span> - <span class="comment"> * @param context</span> - <span class="comment"> * @param attrs</span> - <span class="comment"> */</span> - <span class="keyword">public</span> MyToggleButton(Context context, AttributeSet attrs) { - <span class="keyword">super</span>(context, attrs); - initView(); - } - - <span class="comment">/**</span> - <span class="comment"> * 测量尺寸时的回调方法</span> - <span class="comment"> */</span> - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onMeasure(<span class="keyword">int</span> widthMeasureSpec, <span class="keyword">int</span> heightMeasureSpec) { - <span class="comment">// super.onMeasure(widthMeasureSpec, heightMeasureSpec);</span> - <span class="comment">// 设置当前view的大小 width:view的宽,单位都是像素值 heigth:view的高,单位都是像素值</span> - setMeasuredDimension(backgroundBitmap.getWidth(), - backgroundBitmap.getHeight()); - } - - <span class="comment">// 这个方法对于自定义view的时候帮助不大,因为view的位置一般由父组件来决定的</span> - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onLayout(<span class="keyword">boolean</span> changed, <span class="keyword">int</span> left, <span class="keyword">int</span> top, <span class="keyword">int</span> right, - <span class="keyword">int</span> bottom) { - <span class="keyword">super</span>.onLayout(changed, left, top, right, bottom); - } - - <span class="comment">/**</span> - <span class="comment"> * 画view的方法,绘制当前view的内容</span> - <span class="comment"> */</span> - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onDraw(Canvas canvas) { - <span class="comment">// super.onDraw(canvas);</span> - - Paint paint = <span class="keyword">new</span> Paint(); - <span class="comment">// 打开抗锯齿</span> - paint.setAntiAlias(<span class="keyword">true</span>); - - <span class="comment">// 画背景</span> - canvas.drawBitmap(backgroundBitmap, <span class="number"></span>, <span class="number"></span>, paint); - <span class="comment">// 画滑块</span> - canvas.drawBitmap(slideButton, slideBtn_left, <span class="number"></span>, paint); - } - - <span class="comment">/**</span> - <span class="comment"> * 初始化view</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">void</span> initView() { - backgroundBitmap = BitmapFactory.decodeResource(getResources(), - R.drawable.switch_background); - slideButton = BitmapFactory.decodeResource(getResources(), - R.drawable.slide_button); - - <span class="comment">/*</span> - <span class="comment"> * 点击事件</span> - <span class="comment"> */</span> - setOnClickListener(<span class="keyword">new</span> OnClickListener() { - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) { - - currentState = !currentState; - flushState(); - flushView(); - } - }); - } - - <span class="comment">/**</span> - <span class="comment"> * 刷新视图</span> - <span class="comment"> */</span> - <span class="keyword">protected</span> <span class="keyword">void</span> flushView() { - <span class="comment">// 刷新当前view会导致ondraw方法的执行</span> - invalidate(); - } - - <span class="comment">/**</span> - <span class="comment"> * 刷新当前的状态</span> - <span class="comment"> */</span> - <span class="keyword">protected</span> <span class="keyword">void</span> flushState() { - <span class="keyword">if</span> (currentState) { - slideBtn_left = backgroundBitmap.getWidth() - &#8211; slideButton.getWidth(); - } <span class="keyword">else</span> { - slideBtn_left = <span class="number"></span>; - } - } - - } </div> &nbsp; 在布局文件中将其定义出来: <div class="dp-highlighter bg_html"> <div class="bar"> <div class="tools"> **[html]** [view plain](http://blog.csdn.net/cyp331203/article/details/40736027#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/40736027#)</span></span> <div> <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/505895)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/505895/fork)</span></div> </div> - <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">tools:context</span>=<span class="attribute-value">&#8220;<span class="katex math inline">{relativePackage}.</span>{activityClass}&#8221;</span> <span class="tag">></span> - - - <span class="tag"><</span><span class="tag-name">com.example.togglebutton.ui.MyToggleButton</span> - <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/my_toggle_btn&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_centerInParent</span>=<span class="attribute-value">&#8220;true&#8221;</span> <span class="tag">/></span> - - - <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span> </div> &nbsp; 在这里由于没有写任何点击触发业务的逻辑,只是一个单纯的控件,所以在MainActivity里面没有加入多的代码: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/40736027#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/40736027#)</span></span> <div> <embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/505895)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/505895/fork)</span></div> </div> - <span class="keyword">package</span> com.example.togglebutton; - - <span class="keyword">import</span> android.app.Activity; - <span class="keyword">import</span> android.os.Bundle; - - <span class="keyword">public</span> <span class="keyword">class</span> MainActivity <span class="keyword">extends</span> Activity { - - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) { - <span class="keyword">super</span>.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - } - } </div> 至此一个自定义的开关按钮就完成了,后面两篇将会介绍如何在上面实现 **[点击拖动开关的效果](http://blog.csdn.net/cyp331203/article/details/40779335)** 和如何实现自定义属性,谢谢支持!

2016年4月6日 · 5 分钟 · 天边的星星

Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一)

转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45027641 自定义view/viewgroup要重写的几个方法:onMeasure(),onLayout(),onDraw()。(不熟悉的话可以查看专栏的前几篇文章:Android自定义控件系列二:自定义开关按钮(一))。 今天的任务就是详细研究一下protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法。 如果只是说要重写什么方法有什么用的话,还是不太清楚。先去源码中看看为什么要重写onMeasure()方法,这个方法是在哪里调用的: 一、源码中的measure/onMeasure方法: **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/45027641#) [copy](http://blog.csdn.net/cyp331203/article/details/45027641#) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/642862)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/642862/fork)</span></div> </div> - <span class="keyword">protected</span> <span class="keyword">void</span> onMeasure(<span class="keyword">int</span> widthMeasureSpec, <span class="keyword">int</span> heightMeasureSpec) { - setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), - getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); - } </div> &nbsp; 实际上是在View这个类中的public final void measure(int widthMeasureSpec, int heightMeasureSpec)方法中被调用的: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/45027641#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/45027641#)</span></span> <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/642862)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/642862/fork)</span></div> </div> - <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> measure(<span class="keyword">int</span> widthMeasureSpec, <span class="keyword">int</span> heightMeasureSpec) { - &#8230; - - onMeasure(widthMeasureSpec, heightMeasureSpec); - &#8230; - - } </div> &nbsp; ## <a name="t1"></a>1、measure() 可以看到,measure()这个方法是一个由final来修饰的方法,意味着不能够被子类重写.measure()方法的作用是:测量出一个View的实际大小,而实际性的测量工作,Android系统却并没有帮我们完成,因为这个工作交给了onMeasure()来作,所以我们需要在自定义View的时候按照自己的需求,重写onMeasure方法.而子控件又分为view和viewGroup两种情况,那么测量的流程是怎样的呢,看一下下面这个图你就明白了: ![](http://img.blog.csdn.net/20150413165429783) ## <a name="t2"></a> ## <a name="t3"></a>2、onMeasure onMeasure(int widthMeasureSpec, int heightMeasureSpec)中,两个参数的作用: widthMeasureSpec和heightMeasureSpec这两个int类型的参数,看名字应该知道是跟宽和高有关系,但它们其实不是宽和高,而是由宽、高和各自方向上对应的模式来合成的一个值:其中,在int类型的32位二进制位中,31-30这两位表示模式,0~29这三十位表示宽和高的实际值.其中模式一共有三种,被定义在Android中的View类的一个内部类中:View.MeasureSpec: ①UNSPECIFIED:表示默认值,父控件没有给子view任何限制。&#8212;&#8212;二进制表示:00 ②EXACTLY:表示父控件给子view一个具体的值,子view要设置成这些值的大小。&#8212;&#8212;二进制表示:01 ③AT_MOST:表示父控件个子view一个最大的特定值,而子view不能超过这个值的大小。&#8212;&#8212;二进制表示:10 # <a name="t4"></a>二、MeasureSpec MeasureSpe描述了父View对子View大小的期望.里面包含了测量模式和大小.我们可以通过以下方式从MeasureSpec中提取模式和大小,该方法内部是采用位移计算. int specMode = MeasureSpec.getMode(measureSpec);//得到模式 int specSize = MeasureSpec.getSize(measureSpec);//得到大小 也可以通过MeasureSpec的静态方法把大小和模式合成,该方法内部只是简单的相加. MeasureSpec.makeMeasureSpec(specSize,specMode); 每个View都包含一个ViewGroup.LayoutParams类或者其派生类,LayoutParams中包含了View和它的父View之间的关系,而View大小正是View和它的父View共同决定的。 我们平常使用类似于RelativeLayout和LinearLayout的时候,在其内部添加view的时候,不管是布局文件中加入还是在代码中使用addView方法添加,实际上都会调用这个onMeasure方法,而measure和onMeasure中的两个参数,是由各级父控件往子控件/子view进行一层层传递的。我们可以在xml中定义Layout的宽和高的具体的值或宽高的填充方式:matchparent/wrapcontent,也可以在代码中使用LayoutParams设置,而实际上这里设置的值就会对应到上面的measure和onMeasure方法中的两个参数的模式,对应关系如下: 具体的值(如width=200dp)和matchparent/fillparent,对应模式中的MeasureSpec.EXACTLY 包裹内容(width=wrapcontent)则对应模式中的MeasureSpec.AT_MOST 系统调用measure方法,从父控件到子控件的heightMeasureSpec的传递是有一套对应的判断规则的,列表如下: ![](http://img.blog.csdn.net/20150413170503566) 一个view的宽高尺寸,只有在测量之后才能得到,也就是measure方法被调用之后。大家都应该使用过View.getWidth()和View.getHeight()方法,这两个方法可以返回view的宽和高,但是它们也不是在一开始就可以得到的,比如oncreate方法中,因为这时候measure方法还没有被执行,测量还没有完成,我们可以来作一个简单的实验:自定义一个MyView,继承View类,然后在OnCreate方法中,将其new出来,通过addview方法,添加到现在的布局中。然后调用MyView对象的getWidth()和getHeight()方法,会发现得到的都是0。 onMeasure通过父View传递过来的大小和模式,以及自身的背景图片的大小得出自身最终的大小,然后通过setMeasuredDimension()方法设置给mMeasuredWidth和mMeasuredHeight. 普通View的onMeasure逻辑大同小异,基本都是测量自身内容和背景,然后根据父View传递过来的MeasureSpec进行最终的大小判定,例如TextView会根据文字的长度,文字的大小,文字行高,文字的行宽,显示方式,背景图片,以及父View传递过来的模式和大小最终确定自身的大小. # <a name="t5"></a>三、ViewGroup的onMeasure ViewGroup是个抽象类,本身没有实现onMeasure,但是他的子类都有各自的实现,通常他们都是通过measureChildWithMargins函数或者其他类似于measureChild的函数来遍历测量子View,被GONE的子View将不参与测量,当所有的子View都测量完毕后,才根据父View传递过来的模式和大小来最终决定自身的大小. 在测量子View时,会先获取子View的LayoutParams,从中取出宽高,如果是大于0,将会以精确的模式加上其值组合成MeasureSpec传递子View,如果是小于0,将会把自身的大小或者剩余的大小传递给子View,其模式判定在前面表中有对应关系. ViewGroup一般都在测量完所有子View后才会调用setMeasuredDimension()设置自身大小,如第一张图所示. 可能看到现在,还是没搞清楚Android系统通过measure和onmeasure一层层传递参数的具体方法。在研究这个问题之前,先来看一下最简单的helloworld的UI层级关系图: 为了方便起见,这里我们使用requestWindowFeature(Window.FEATURE_NO_TITLE);去除标题栏的影响,只看层级关系。 <div class="dp-highlighter bg_html"> <div class="bar"> <div class="tools"> **[html]** [view plain](http://blog.csdn.net/cyp331203/article/details/45027641#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/45027641#)</span></span> <div> <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/642862)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/642862/fork)</span></div> </div> - <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">tools:context</span>=<span class="attribute-value">&#8220;<span class="katex math inline">{relativePackage}.</span>{activityClass}&#8221;</span> <span class="tag">></span> - - <span class="tag"><</span><span class="tag-name">TextView</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;@string/hello_world&#8221;</span> <span class="tag">/></span> - - <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span> </div> &nbsp; <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools"> **[java]** [view plain](http://blog.csdn.net/cyp331203/article/details/45027641#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/cyp331203/article/details/45027641#)</span></span> <div> <embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/642862)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/642862/fork)</span></div> </div> - <span class="keyword">package</span> com.example.hello; - - <span class="keyword">import</span> android.app.Activity; - <span class="keyword">import</span> android.os.Bundle; - <span class="keyword">import</span> android.view.Window; - - <span class="keyword">public</span> <span class="keyword">class</span> MainActivity <span class="keyword">extends</span> Activity { - - <span class="annotation">@Override</span> - <span class="keyword">protected</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) { - <span class="keyword">super</span>.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_NO_TITLE); - setContentView(R.layout.activity_main); - } - } </div> UI层级关系图: ![](http://img.blog.csdn.net/20150413172415210) 可以发现最简单的helloworld的层级关系图是这样的,最开始是一个PhoneWindow的内部类DecorView,这个DecorView实际上是系统最开始加载的最底层的一个viewGroup,它是FrameLayout的子类,然后加载了一个LinearLayout,然后在这个LinearLayout上加载了一个id为content的FrameLayout和一个ViewStub,这个实际上是原本为ActionBar的位置,由于我们使用了requestWindowFeature(Window.FEATURE_NO_TITLE),于是变成了空的ViewStub;然后在id为content的FrameLayout才加载了我们的布局XML文件中写的RelativeLayout和TextView。 那么measure方法在系统中传递尺寸和模式,必定是从DecorView这一层开始的,我们假定手机屏幕是320*480,那么DecorView最开始是从硬件的配置文件中读取手机的尺寸,然后设置measure的参数大小为320*480,而模式是EXCACTLY,传递关系可以由下图示意: ![](http://img.blog.csdn.net/20150413174301575) <div> </div> &nbsp; 好了,原理将到这里,下一篇将看到利用onMeasure来测量一个自定义一个ImageView,使其能够自动填满屏幕的宽度,且能通过measure测量高度,自适应的调整高度,永远不出现拉伸/压缩变形的情况,敬请关注,谢谢。 [Android自定义控件系列八:详解onMeasure()(二)&#8211;利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题](http://blog.csdn.net/cyp331203/article/details/45038329) **转载请注明出处:[http://blog.csdn.net/cyp331203/article/details/45027641](http://blog.csdn.net/cyp331203/article/details/45027641)**

2016年4月6日 · 2 分钟 · 天边的星星

利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

使用ImageView会遇到的问题 转载请注明出处:http://blog.csdn.net/cyp331203/article/details/45038329 在Android应用中,都少不了图片的显示,ImageView,轮播图,ViewPager等等,很多都是来显示图片的,比如一个广告条的轮播效果,参看博客:广告条效果实现—-ViewPager加载大图片(LruCache)以及定时刷新,很多时候,我们都希望图片能够在宽度上填充父窗体,这样比较符合人的审美观点,但是问题就随之而来了,那就是高度如何定义??先来看一个普通的ImageView的 Xml布局文件的定义: **[html]** [view plain](http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/cyp331203/article/details/45038329)[copy](http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/cyp331203/article/details/45038329)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/643475)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/643475/fork) <div> </div> <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="tag"><</span><span class="tag-name">LinearLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">xmlns:tools</span>=<span class="attribute-value">&#8220;http://schemas.android.com/tools&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:orientation</span>=<span class="attribute-value">&#8220;vertical&#8221;</span> <span class="tag">></span> - - <span class="tag"><</span><span class="tag-name">ImageView</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;fill_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:src</span>=<span class="attribute-value">&#8220;@drawable/recommend_39&#8221;</span> <span class="tag">/></span> - - <span class="tag"><</span><span class="tag-name">TextView</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:text</span>=<span class="attribute-value">&#8220;描述文字信息&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.&#8221;</span> <span class="tag">/></span> - - <span class="tag"></</span><span class="tag-name">LinearLayout</span><span class="tag">></span> 为了方便查看,我在ImageView下面又加上了一句描述的信息的TextView,这时,父控件都是填充父窗体,而ImageView则是:横向填充父窗体,纵向包裹内容;text都是包裹内容;那么来看看显示效果: ...

2016年4月6日 · 5 分钟 · 天边的星星

使用Gradle发布Android开源项目到JCenter

欢做些开源项目的朋友,相信有不少人都希望能把自己的项目发布到公共的中央仓库,如maven中央仓库,以供别人方便地集成使用。而使用了Android Studio的同学,应该也对gradle和jcenter印象深刻,不少开源库都是发布到这里的。这一篇就主要来介绍一下,如何使用Gradle发布到jcenter。 转载:http://blog.csdn.net/maosidiaoxian/article/details/43148643 注册 先到https://bintray.com注册一个账号。 配置账号 我们需要配置一下BINTRAY_USER及BINTRAY_KEY两个属性。BINTRAY_USER即你注册的账号名,BINTRAY_KEY可通过以下方法找到。 如图所示,先点击你的账号名称进入个人页面。 ![](http://img.blog.csdn.net/20150126092456203?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 然后点击Edit,进入编辑页面。 ![](http://img.blog.csdn.net/20150126092541646?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 接着点击API key,再点右边的Show就可以看到API KEY了。 ![](http://img.blog.csdn.net/20150126092533531?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 然后到你的.gradle目录下(如果你没有配置过GRADLE_USER_HOME的环境变量,则是在你的用户目录下),编辑gradle.properties(如果没有则创建),加入配置: **[plain]** [view plain](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)</span></span> <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/589055)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/589055/fork)</span> </div> </div> - BINTRAY_USER=xxx - BINTRAY_KEY=xxx 配置项目 下载我的这个项目:https://github.com/msdx/gradle-publish,把gradle.properties拷贝到你的项目中,并配置这些属性。 然后参考这里的build.gradle,在你的build.gradle上面加入: **[java]** [view plain](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)</span></span> <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/589055)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/589055/fork)</span> </div> </div> - buildscript { - repositories { - jcenter() - } - dependencies { - classpath <span class="string">&#8216;com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0&#8217;</span> - } - } 再加上一句: **[java]** [view plain](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/maosidiaoxian/article/details/43148643#)</span></span> <div> <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3"> </embed> </div> <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/589055)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/589055/fork)</span> </div> </div> - apply from: <span class="string">&#8216;你的bintray.gradle的相对路径&#8217;</span> 你的bintray.gradle可以参考我这个项目的bintray.gradle 来写一下。我这里的bintray.gradle是用来发布android项目的,发布的文件包括源码,文档以及AAR,如果你也是要发布这些,则可以直接使用。 执行命令进行发布 配置完成后,执行gradle bintray,即会进行编译、打包以及发布。 包含到jcenter中央库 先进入此页面:https://bintray.com/bintray/jcenter。 然后点击Include My Package,如下图: ![](http://img.blog.csdn.net/20150202091406259?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 然后在弹出的对话框中搜索并勾上你的项目。 ![](http://img.blog.csdn.net/20150202091431609?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 然后你可以写一下你的提交请求(貌似也可以不写?),点“Send”,接下来就看管理员审核了。 ![](http://img.blog.csdn.net/20150202091438535?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFvc2lkaWFveGlhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 审核 等待管理员审核。通常都很快能通过。如果你比较心急,那么在审核通过之前,可以以maven {url http://dl.bintray.com/你的用户名/maven}的方式对你的仓库进行声明。 ## 补充说明 如果添加上这段脚本之后,在android studio中运行项目会出错,请注释apply from那一句。出错原因在于它会找不到我打包aar的那个任务,但是在命令行下是可以的。如果有更好的打包aar的方法,欢迎交流。

2016年3月16日 · 1 分钟 · 天边的星星

[Publish AAR To Maven] 使用 Gradle 发布 AAR 到 Maven 仓库

======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:github.com/qiujuer/Genius-Android 转载请注明出处:http://blog.csdn.net/qiujuer/article/details/44195131 ——学之开源,用于开源;初学者的心态,与君共勉! ======================================================== 有一个好的库想与世界的伙伴分享,于是共享到GitHub上,于是有人看到了,但是要使用却发现配置非常难。但是发现别人的库只需要一行代码却能使用;于是我想知道为什么能这么简单。 在这篇文章中将带你了解如何发布你的库到远程仓库Maven中,又如何使用。 # <a name="t0"></a>准备 开始之前我们有一定的准备工作,如果准备好了那么后面将会非常顺畅。 - [注册 https://issues.sonatype.org 账户](http://blog.csdn.net/qiujuer/article/details/44195199),并创建你的 Group Id - 学会GPGTools的使用,并生成你的密钥对;见:[使用GPG对文件进行签名加密](http://blog.csdn.net/qiujuer/article/details/44173611) - 编写你的库,并准备好发布,工具:[Android-Studio](http://blog.csdn.net/qiujuer/article/details/41843095) - 添加发布Maven的Gradle文件 - 添加你的个人信息,如你的发布地址、库版本信息等 - 开发发布快照、以及正式版本,审核 # <a name="t1"></a>开始 前面的两项工作由于篇幅较大,单独开篇了,欢迎大家去看~~,我们从第三的地方开始。 ## <a name="t2"></a>编写Lib 编写库,这里我采用的是Android-Studio;至于其使用建立过程以及简单使用大家可见:[环境配置之正式版Android Studio 1.0](http://blog.csdn.net/qiujuer/article/details/41843095) 在这里我使用 [Genius-Android](https://github.com/qiujuer/Genius-Android) 开源库进行演示。 在本次项目中我们尝试发布 UI 部分,图中圈起来部分为我们需要的文件。 ## <a name="t3"></a>编写发布文件 发布文件就是其中的 **maven_push.gradle** 。由于代码较长就不贴代码了,大家可以去GitHub上查看。 代码已经发布到 BeFoot 开源项目中. 该代码运行在 Gradle 中,作用是按照配置进行打包代码文件,然后签名文件,最后发布你的文件到仓库。 在该代码中可以看见许多的方法与参数,如: ``` def isReleaseBuild() { &lt;span class="hljs-keyword">return&lt;/span> VERSION_NAME.contains(&lt;span class="hljs-string">"SNAPSHOT"&lt;/span>) == &lt;span class="hljs-keyword">false&lt;/span> } ...

2016年3月16日 · 2 分钟 · 天边的星星

使用Gradle发布项目到JCenter仓库

编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! 原文:使用Gradle发布项目到JCenter仓库 这篇文章介绍通过Gradle把开源项目发布到公共仓库JCenter中,方便你我他的事情,我们都是很懒的嘛。JCenter现在是Android Studio中repositories的默认节点了,之前是Maven的,不过JCenter是兼容Maven的,所以放心使用。步骤基本是按Publishing Gradle Android Library to jCenter Repository这里来的,英文能看的直接看这篇也行。下面我的步骤正式开始,发布到JCenter仓库的是我的项目:BounceProgressBar。 申请Bintray账号 Bintray的基本功能类似于Maven Central,一样的我们需要一个账号,Bintray传送门,注册完成后第一步算完成了。 生成项目的JavaDoc和source JARs 简单的说生成的这两样东西就是我们在下一步中上传到远程仓库JCenter上的文件了。这一步需要android-maven-plugin插件,所以我们需要在项目的build.gradle(Top-level build file,项目最外层的build.gradle文件)中添加这个构建依赖,如下: 1 <div class="line number2 index1 alt1"> 2 </div> <div class="line number3 index2 alt2"> 3 </div> <div class="line number4 index3 alt1"> 4 </div> <div class="line number5 index4 alt2"> 5 </div> <div class="line number6 index5 alt1"> 6 </div> <div class="line number7 index6 alt2"> 7 </div> <div class="line number8 index7 alt1"> 8 </div> <div class="line number9 index8 alt2"> 9 </div> <div class="line number10 index9 alt1"> 10 </div> <div class="line number11 index10 alt2"> 11 </div> <div class="line number12 index11 alt1"> 12 </div> <div class="line number13 index12 alt2"> 13 </div> <div class="line number14 index13 alt1"> 14 </div> <div class="line number15 index14 alt2"> 15 </div> <div class="line number16 index15 alt1"> 16 </div> </td> <td class="code"> <div class="container"> <div class="line number1 index0 alt2"> `buildscript {` </div> <div class="line number2 index1 alt1"> ` ``repositories {` </div> <div class="line number3 index2 alt2"> ` ``jcenter()` </div> <div class="line number4 index3 alt1"> ` ``}` </div> <div class="line number5 index4 alt2"> ` ``dependencies {` </div> <div class="line number6 index5 alt1"> ` ``classpath ``'com.android.tools.build:gradle:1.0.0'` </div> <div class="line number7 index6 alt2"> ` ``classpath ``'com.github.dcendents:android-maven-plugin:1.2'` </div> <div class="line number8 index7 alt1"> ` ``// NOTE: Do not place your application dependencies here; they belong` </div> <div class="line number9 index8 alt2"> ` ``// in the individual module build.gradle files` </div> <div class="line number10 index9 alt1"> ` ``}` </div> <div class="line number11 index10 alt2"> `}` </div> <div class="line number12 index11 alt1"> `allprojects {` </div> <div class="line number13 index12 alt2"> ` ``repositories {` </div> <div class="line number14 index13 alt1"> ` ``jcenter()` </div> <div class="line number15 index14 alt2"> ` ``}` </div> <div class="line number16 index15 alt1"> `}` </div> </div> </td> </tr> </table> 然后在你需要发布的那个module(我这里的即是library)的build.gradle里配置如下内容: ...

2016年3月16日 · 11 分钟 · 天边的星星

GitHub 上排名前 100 的 Android 开源库简介

本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择 (Best Match) 得到的结果, 然后过滤了跟Android不相关的项目, 所以排名并不具备任何官方效力, 仅供参考学习, 方便初学者快速了解当前一些流行的Android开源库. iOS 版本的在此: https://github.com/Aufree/trip-to-iOS/blob/master/Top-100.md 感谢 @GitHubDaily 的大力支持, 以及 @stormzhang 的指点 若有任何疑问可通过邮件或微博联系我 项目名称 <th> 项目简介 </th> 1. [react-native](https://github.com/facebook/react-native) <td width="275"> 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native, 该框架结合了 Web 应用和 Native 应用的优势, 可以使用 JavaScript 来开发 iOS 和 Android 原生应用 </td> 2.[Android-Universal-Image-Loader](https://github.com/nostra13/Android-Universal-Image-Loader) <td width="275"> ImageLoader 是最早开源的 Android 图片缓存库, 强大的缓存机制, 早期被广泛 Android 应用使用, 至今仍然有很多 Android 开发者在使用 </td> 3. [RxJava](https://github.com/ReactiveX/RxJava) <td width="275"> RxJava 是一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库, 简单来说它就是一个实现异步操作的库, RxJava 的优点在于一个词 &#8220;简洁&#8221;, 使用它就算你程序逻辑有多么复杂, 它依然能够保持简洁易懂 </td> 4. [retrofit](https://github.com/square/retrofit) <td width="275"> Retrofit 是 Square 公司出品的 HTTP 请求库, 同时是 Square 是最早开源项目之一, Retrofit 是目前 Android 最流行的 Http Client 库之一, 目前版本是 Retrofit2.0 Beta4, 越来越多 Android 开发者开始使用这个请求库了 </td> 5. [okhttp](https://github.com/square/okhttp) <td width="275"> OkHttp 是 Square 公司出品的 HTTP 另一个请求库, Google 不推荐人们使用 HttpClient, 可是 HttpURLConnection 实在是太难用了, 因此很多人使用了 OkHttp 来解决这问题, 据说 Android4.4 的源码中可以看到 HttpURLConnection 已经替换成 OkHttp 实现呢 </td> 6. [SlidingMenu(不建议使用)](https://github.com/jfeinstein10/SlidingMenu) <td width="275"> 一个侧滑菜单开源库, 在 Google 自己原生态的侧滑菜单 NavigationDrawer 没有出现之前, 这个库就已经被广泛使用, 可是到现在这个库已经被放弃了 </td> 7. [picasso](https://github.com/square/picasso) <td width="275"> Picasso 是 Square 公司出品的一款图片缓存库, 主导者是 JakeWharton 大神 </td> 8. [android-best-practices](https://github.com/futurice/android-best-practices) <td width="275"> Android 开发最佳实践, 里面所介绍的经验都是来自于 Futurice 公司 Android 开发者, 介绍内容有 Android 开发规范、架构、布局技巧, 以及使用一些有助于快速开发相关工具等等, 非常适合新手去学习 </td> 9. [EventBus](https://github.com/greenrobot/EventBus) <td width="275"> EventBus 是 Android 事件管理总线, 使用它可以替带 Android BroadCast, BroadCastReceiver, Handler 在 Activity, Fragment, Service, 线程之间传递消息, 大大简化了事件传递逻辑 </td> 10. [android-async-http](https://github.com/loopj/android-async-http) <td width="275"> Android-Async-Http 是 Android 一款老牌异步请求库, 专门对 Android 在 Apache 的 HttpClient 基础上构建的异步 http 连接, 该库有很多特征, 例如: 库的 size 小, 支持文件上传不需使用第三方库支持, 内部使用线程池来处理并发, 等等 </td> 11. [fresco](https://github.com/facebook/fresco) <td width="275"> Fresco 是 FaceBook 公司出品的一款图片缓存库, Fresco 是一个强大的图片加载组件, 支持加载 Gif 图和 WebP 格式, 支持 Android2.3(API level 9) 及其以上系统, Fresco 中设计了 Image pipeline 和 Drawees 两个模块各施其职, 使得图片完美加载出来, 想知道更多 image pipeline 和 Drawees 有关于它的特性, 可以到它[官方平台](http://fresco-cn.org/)看介绍 </td> 12. [zxing](https://github.com/zxing/zxing) <td width="275"> ZXing 是二维码领域中名气最大的开源项目, 它提供了多个平台的二维码/条形码扫描解决方案, 拥有扫描快, 识别率高, 使用简单等特点 </td> 13. [leakcanary](https://github.com/square/leakcanary) <td width="275"> LeakCanary 是 Square 公司出的一款检测内存泄露工具, 该工具能帮助你在开发阶段方便的检测出内存泄露的问题, 使用起来非常简单方便 </td> 14. [butterknife](https://github.com/JakeWharton/butterknife) <td width="275"> 由 JakeWharton 大神开发出来的, ButterKnife 是 View 注入框架, 使用它为了简写很多 findViewById 代码, 同时还支持 View 的一些事件处理函数 </td> 15. [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) <td width="275"> MPAndroidChart 是一款强大的 Android 图表库, 支持各种各样图表显示, 能想到的图表样式这里几乎都有, 图表还支持选择, 拖放和缩放动画效果 </td> 16.[ActionBarSherlock(不建议使用)](https://github.com/JakeWharton/ActionBarSherlock) <td width="275"> ActionBarSherlock 这个库是 JakeWharton 大神开发出来支持 Android3.0 以下版本的, 后来慢慢的 Google 也提供了 AppCompat 库来支持 Android3.0 以下版本使用 ActionBar, 因此作者不建议我们再使用这个库了 </td> 17. [androidannotations](https://github.com/excilys/androidannotations) <td width="275"> AndroidAnnotations 是一个能够让你快速进行 Android 开发的开源框架, 它能让你专注于真正重要的地方, 使代码更加精简, 使项目更加容易维护, 它的目标就是 &#8220;Fast Android Development.Easy maintainance&#8221; </td> 18. [ViewPagerIndicator](https://github.com/JakeWharton/ViewPagerIndicator) <td width="275"> 由 JakeWharton 大神开发出来的一个 ViewPager 指示器, 使用起来简单方便, 可高度定制, 开发出各种各样动画效果 </td> 19. [glide](https://github.com/bumptech/glide) <td width="275"> Glide 是 Google 员工的开源项目, 广泛应用于 Google 一些 App 上, 在2014年 Google I/O 大会上被推荐使用, Glide 和 Picasso 被人拿来比较研究过, Glide 与 Picasso 有 90% 的相似度, 但在一些细节上还是有点区别的, 各有各优缺点看君选择 </td> 20. [HomeMirror](https://github.com/HannahMitt/HomeMirror) <td width="275"> 开发者是由一名程序媛 Hannah Mittelstaedt , HomeMirror 是一款 Android 镜子应用, 目前它能实现日期, 时间, 天气, 生日信息, 事件提醒器, 骑车天气的推荐, 股票信息, XKCD 漫画网站的新帖等等 </td> 21. [Android-PullToRefresh(不建议使用)](https://github.com/chrisbanes/Android-PullToRefresh) <td width="275"> 一个强大的拉动刷新开源项目,支持各种控件下拉刷新,ListView、ViewPager、WebView、ExpandableListView、GridView、ScrollView、Horizontal ScrollView、Fragment 上下左右拉动刷新, 不过现在这个项目已经停止维护更新了, 推荐使用 Android-Ultra-Pull-to-Refresh </td> 22. [MaterialDesignLibrary](https://github.com/navasmdc/MaterialDesignLibrary) <td width="275"> 这个库控件都是遵循了 Google Material Design 设计规范开发出来, 例如有: Flat Button, Rectangle Button, CheckBox, Switch, Progress bar circular indeterminate 等等 </td> 23. [PhotoView](https://github.com/chrisbanes/PhotoView) <td width="275"> PhotoView 是 ImageView 的子类, 支持所有 ImageView 的源生行为, 例如: 支持 Pinch 手势自由缩放, 支持双击放大/还原, 支持平滑滚动等等, 并且非常方便的与 ImageLoader/Picasso 之类的网络图片读取库集成使用, 还方便的与 ViewPager 等同样支持滑动手势的控件集成 </td> 24. [RxAndroid](https://github.com/ReactiveX/RxAndroid) <td width="275"> 由 JakeWharton 大神主导开发的项目, RxAndroid 是 RxJava 的一个针对 Android 平台的扩展, 主要用于 Android 开发 </td> 25. [material-dialogs](https://github.com/afollestad/material-dialogs) <td width="275"> Material Dialogs 是一个可高度定制易用, 符合 Material Design 风格的 Dialogs, 兼容 Android API8 以上版本, 个人使用感觉它完全可替代 Android 原生那个, 比原生那个更加简单易用 </td> 26.[Android-ObservableScrollView](https://github.com/ksoichiro/Android-ObservableScrollView) <td width="275"> ObservableScrollView 是一款用于在滚动视图中观测滚动事件的 Android 库, 它能够轻而易举地与 Android 5.0 Lollipop 引进的工具栏 (Toolbar) 进行交互, 还可以帮助开发者实现拥有 Material Design 应用视觉体验的界面外观, 支持ListView, ScrollView, WebView, RecyclerView, GridView组件 </td> 27. [Android-Bootstrap](https://github.com/Bearded-Hen/Android-Bootstrap) <td width="275"> Android 版的 Bootstrap, 利用这个库能够实现很多 Bootstrap 样式风格, 之前有学过 Html 的人就知道 Bootstrap 是什么玩意啦 </td> 28. [AndroidSwipeLayout](https://github.com/daimajia/AndroidSwipeLayout) <td width="275"> 开发者是代码家, AndroidSwipeLayout 是一个支持ListView, GridView, ViewGroup等等左右上下滑动出操作菜单, 类似 qq 消息列表向左滑动显示出多某条信息的操作菜单 </td> 29. [dagger](https://github.com/square/dagger) <td width="275"> Dagger 是 Square 公司出品的一个针对 Android 和 Java 的快速依赖注入器, 能够有效减少你敲代码量 </td> 30. [ListViewAnimations](https://github.com/nhaarman/ListViewAnimations) <td width="275"> 一个轻轻松松给 Android ListView 添加动画效果的库, 支持的动画有: Alpha, SwingRightIn, SwingLeftIn, SwingBottomIn, SwingRightIn and ScaleIn等等, 使用它能很容易就实现帅爆的效果 </td> 31. [PagerSlidingTabStrip](https://github.com/astuetz/PagerSlidingTabStrip) <td width="275"> PagerSlidingTabStrip 是一个给 Android ViewPager添加上 ViewPager 滑动指示器, 从 GitHub 上面看, 这个库似乎没有人在维护了, 请谨慎使用该库 </td> 32. [AndroidViewAnimations](https://github.com/daimajia/AndroidViewAnimations) <td width="275"> 开发者是代码家, 这个库实现很多很酷炫的 Android 动画, 动画效果是借鉴 Animate.css 来实现的, 非常酷, 而且这个使用起来也是非常简单 </td> 33. [AndroidSlidingUpPanel](https://github.com/umano/AndroidSlidingUpPanel) <td width="275"> AndroidSlidingUpPanel 是一个上拉面板, 就是向上滑动的时候往上飞出一个显示面板控件, 该库效果在 Google Music, Google Maps and Rdio等 App 应用到 </td> 34. [MaterialDrawer](https://github.com/mikepenz/MaterialDrawer) <td width="275"> MaterialDrawer 是一个类似 Google 官方 NavigationView 侧滑显示控件, 个人认为 NavigationView 并没有 MaterialDrawer 实用, 因为 NavigationView 自由度不是很好, 很多都写死了不可以自由定义布局, 而 MaterialDrawer 能够实现跟 NavigationView 一样的效果, 同时还支持自定义效果, 自由度非常高 </td> 35. [Material-Animations](https://github.com/lgvalle/Material-Animations) <td width="275"> Material-Animations 是一个很好过渡动画库, 可以应用于 Activity 与 Activity 之间的跳转, Fragment 与 Fragment 之间的跳转, 以及各个 View 变化前后的过渡动画 </td> 36. [MaterialViewPager](https://github.com/florent37/MaterialViewPager) <td width="275"> 一个简单易用 Material Design 风格的 ViewPager 库 </td> 37. [ion](https://github.com/koush/ion) <td width="275"> ion 是一个让 Android 的网络操作变得极其简单, 支持异步获取和处理JSON, 支持 Android 文件下载 (同时支持下载进度条绑定), 支持安全链接和代理 </td> 38. [stetho](https://github.com/facebook/stetho) <td width="275"> Stetho是 Facebook 出品的一个强大的 Android 调试工具,使用该工具你可以在 Chrome Developer Tools查看App的布局, 网络请求(仅限使用Volley, okhttp的网络请求库), sqlite, preference, 一切都是可视化的操作,无须自己在去使用adb, 也不需要root你的设备 </td> 39. [fastjson](https://github.com/alibaba/fastjson) <td width="275"> Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景 </td> 40. [cardslib](https://github.com/gabrielemariotti/cardslib) <td width="275"> Cardslib 是早期由 Gabriele Mariotti 开发的一个为开发者方便实现各种 Card UI 的 Android 开源代码库, 后来 Google 官方提供自己封装了 CardView 在 v7 包下, 使用 Google 官方的可以完全替代了这个库, 因此这个也被弃用了 </td> 41. [Android-Ultra-Pull-To-Refresh](https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh) <td width="275"> 开发者是廖祜秋, 这个是一个非常强大的下拉刷新库, 继承 ViewGroup 可以包含任何 View, 功能甚至比 SwipeRefreshLayout 强大, 使用起来也非常容易, 还可以自由定制自己的 UI 样式 </td> 42. [greenDAO](https://github.com/greenrobot/greenDAO) <td width="275"> greenDAO 是一个可以帮助 Android 开发者快速将 Java 对象映射到 SQLite 数据库的表单中的 ORM解决方案, 通过使用一个简单的面向对象 API, 开发者可以对 Java 对象进行存储, 更新, 删除和查询, greenDAO 相对 OrmLite, AndrORM 这两个 ORM 开源库, 性能是最高的 </td> 43. [AndroidStaggeredGrid](https://github.com/etsy/AndroidStaggeredGrid) <td width="275"> AndroidStaggeredGrid 是一个支持多列并且每一行的 item 大小不一, 交错排列的 GridView, 就是实现瀑布流样式效果, 目前该库已经被弃用了, 开发者建议我们使用 Google 官方控件 RecyleView 中的 StaggeredGridLayoutManager 布局来实现瀑布流效果 </td> 44. [otto](https://github.com/square/otto) <td width="275"> Otto 是 Square 公司出的一个事件库 (pub/sub 模式), 用来简化应用程序组件之间的通讯, otto 修改自 Google 的 Guava 库, 专门为 Android 平台进行了优化, 与上面介绍的 EventBus 相比, 两个库各有各的优点, 完全取决于我们自己项目的需求来选择它们哪一个 </td> 45. [xUtils](https://github.com/wyouflf/xUtils) <td width="275"> xUtils 是一个快速开发框架, 里面包含 DbUtils, ViewUtils, HttpUtils, BitmapUtils 四大模块, 可用于快速开发, 支持大文件上传, 拥有更加灵活的 ORM, 最低兼容 Android 2.2 </td> 46. [realm-java](https://github.com/realm/realm-java) <td width="275"> Realm 一个轻量的 Android 版本的数据存储库, 比 Android 原生系统的 SQLite 更加简洁快速对数据进行操作 </td> 47.[Android-CleanArchitecture](https://github.com/android10/Android-CleanArchitecture) <td width="275"> CleanArchitecture 是一个非常典型使用 MVP 架构的项目, 大家如果还没有理解 MVP 架构的可以看看这个项目 </td> 48. [StickyListHeaders](https://github.com/emilsjolander/StickyListHeaders) <td width="275"> StickyListHeaders 是一个实现能够固定在屏幕顶部的ListView Section Header库, 就是当前 section 的 header 固定在屏幕顶部, 当滑动到其他 section 时, 其他 section 的 header 会代替之前的 section 的 header, 固定到屏幕顶部, 类似于 Android4.0 的手机通讯录的效果 </td> 49. [AppIntro](https://github.com/PaoloRotolo/AppIntro) <td width="275"> AppIntro 是一个让人轻松快速搭建漂亮酷炫的引导页库 </td> 50. [ActiveAndroid](https://github.com/pardom/ActiveAndroid) <td width="275"> ActiveAndroid 是采用Rails中的 [Active Record](http://en.wikipedia.org/wiki/Object-relational_mapping)架构模式设计的适用于 Android 平台的轻量级 ORM 架构, 几乎可以不用写任何 SQL 代码实现快速开发 </td> 51. [android-volley](https://github.com/mcxiaoke/android-volley) <td width="275"> Volley 是谷歌官方开发团队在 2013 年 Google I/O 大会推出的一个新的网络通信框架, 这个框架把 AsyncHttpClient 和 Universal-Image-Loader 的优点集于了一身,既可以像AsyncHttpClient 一样非常简单地进行 HTTP 通信,也可以像 Universal-Image-Loader 一样轻松加载网络上的图片, 这个库并不是官方的, 只是托管同步在 Maven, 官方只提供的 Jar 包 </td> 52. [twoway-view](https://github.com/lucasr/twoway-view) <td width="275"> TwoWayView 是简化 RecyclerView 开发的一个库, 可以在其 Base LayoutManager 基础上构建各种各样的布局, 该库内置了几个常用布局 List, Grid, Staggered Grid,Spannable Grid </td> 53. [ShowcaseView](https://github.com/amlcurran/ShowcaseView) <td width="275"> ShowcaseView 是一个非常适合用于对用户进行第一次使用进行指导的库,使用起来非常简单还可以自定义样式 </td> 54. [Calligraphy](https://github.com/chrisjenx/Calligraphy) <td width="275"> Calligraphy 是一个用来简化 Android 应用使用自定义字体的类库, 该类库会自动查找应用中的 TextView 并设置其使用的字体 </td> 55. [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) <td width="275"> NineOldAndroids 由 JakeWharton 大神开发的一个向下兼容的动画库, 主要是使低于API 11的系统也能够使用 View 的属性动画, 不过现在 JakeWharton 大神已经不推荐使用该库, 而是推荐我们使用官方封装在 Support 库里面的动画 </td> 56. [android-floating-action-button](https://github.com/futuresimple/android-floating-action-button) <td width="275"> FloatingActionButton 是一个悬浮操作按钮, 官方在 Support Design 包下也有封装一个类似这个库效果的 FloatingActionButton, 值得说明的是这个库是早在官方封装之前就存在的, 个人感觉这个库比官方那个更加好用 </td> 57. [CircleImageView](https://github.com/hdodenhof/CircleImageView) <td width="275"> CircleImageView 是一个轻松帮你实现圆形效果 ImageView 图片库, CircleImageView 是基于 ImageView 扩展出来, 因此它拥有 ImageView 控件所有属性, 简单易用值得你使用的库 </td> 58. [material](https://github.com/rey5137/material) <td width="275"> Material 是将 Material Design 风格控件封装在该库当中, 目前封装有Progress, Button, Switch, Slider, Spinner, Text Field, TabPageIndicator, SnackBar, Dialog, BottomSheetDialog, Dynamic theme </td> 59. [ActionBar-PullToRefresh](https://github.com/chrisbanes/ActionBar-PullToRefresh) <td width="275"> ActionBar-PullToRefresh 是一个下拉刷新, 下拉刷新时在 ActionBar 出现加载中提示的库 </td> 60. [FloatingActionButton](https://github.com/makovkastar/FloatingActionButton) <td width="275"> 又一个悬浮操作按钮库, 该库添加支持监听滑滚动事件, 当向下滑时按钮隐藏, 向上滑时按钮显示, 还有动画效果, 支持监听 ListView, ScrollView, RecylerView </td> 61. [AndroidAsync](https://github.com/koush/AndroidAsync) <td width="275"> AndroidAsync 是一款基于 NIO 的低端 Android 异步 socket, http (client+server), websocket 和 socket.io 网络通信协议类库 </td> 62. [rebound](https://github.com/facebook/rebound) <td width="275"> Rebound 是 Facebook 推出的一个弹性动画库, 可以让动画看起来真实自然, 像真实世界的物理运动, 带有力的效果, 使用的参数则是 Facebook 的 origami 中使用的 </td> 63. [android-common](https://github.com/Trinea/android-common) <td width="275"> android-common-lib 是 Trinea 大神收集的一些开发通用的缓存, 公共 View 以及一些常用工具类 </td> 64. [RippleEffect](https://github.com/traex/RippleEffect) <td width="275"> RippleEffect 是一个实现在 Android 任何组件点击出现 Material Design 的波纹效果, 向下兼容到 Android API9 </td> 65. [SmoothProgressBar](https://github.com/castorflex/SmoothProgressBar) <td width="275"> SmoothProgressBar 是一个帮你的 App 方便实现可定制, 平滑动画的水平滚动进度条库 </td> 66. [recyclerview-animators](https://github.com/wasabeef/recyclerview-animators) <td width="275"> RecyclerView Animators 是一个对 Recycler 控件的 Item 添加以及删除增加动画效果, 动画效果有Scale, Fade, Flip, Slide 里面各种各样效果 </td> 67. [circular-progress-button](https://github.com/dmytrodanylyk/circular-progress-button) <td width="275"> 一个带进度显示的 Button, 效果和动画做的都非常赞 </td> 68. [DroidPlugin](https://github.com/Qihoo360/DroidPlugin) <td width="275"> DroidPlugin 是 360 手机助手在 Android 系统上实现了一种新的插件机制: 它可以在无需安装, 修改的情况下运行APK文件, 此机制对改进大型APP的架构, 实现多团队协作开发具有一定的好处 </td> 69. [dynamic-load-apk](https://github.com/singwhatiwanna/dynamic-load-apk) <td width="275"> 开发者是singwhatiwanna(任玉刚), 是《Android 开发艺术探索》书籍的作者, 这个是作者联合另两位开发者啸(时之沙)和宋思宇花了几个月时间研究出来的 Apk 动态加载框架, 想了解更多关于这框架可到作者博客看 [这篇文章](http://blog.csdn.net/singwhatiwanna/article/details/39937639) 有详细介绍 </td> 70. [ExoPlayer](https://github.com/google/ExoPlayer) <td width="275"> ExoPlayer 是Google 开发团队开源出来的一个媒体播放库, 比 Android 框架原生的 MediaPlayer 拥有更多优点支持动态的自适应流 HTTP(DASH) 和 平滑流, 支持高级的HLS特性, 支持自定义和扩治你的使用场景等等 </td> 71. [Crouton](https://github.com/keyboardsurfer/Crouton) <td width="275"> Crouton 是一个显示提示信息的显示工具类, 可以用来代替Toast, 默认显示在窗口的顶部, 可以按队列一个接着一个显示, 不过该库已经被弃用, 不推荐使用 </td> 72. [robospice](https://github.com/stephanenicolas/robospice) <td width="275"> RoboSpice 是一个使你建立异步的长时间的运行任务异常轻松的一个网络库,在网络请求,缓存支持,和提供开箱即用的rest请求方面尤为强大 </td> 73. [hugo](https://github.com/JakeWharton/hugo) <td width="275"> Hugo 是 JakeWharton 大神推出的一个用于打印 Log, hugo 是基于注解被调用的, 引入相关依赖后, 在方法上加上 @DebugLog 即可输出 Log, 使用非常简单 </td> 74. [async-http-client](https://github.com/AsyncHttpClient/async-http-client) <td width="275"> AsyncHttpClient 是又一款 Android 异步请求库, 该库支持 WebSocket 协议, 使用起来也比较简单易用 </td> 75. [UltimateRecyclerView](https://github.com/cymcsg/UltimateRecyclerView) <td width="275"> UltimateRecyclerView 是一个功能强大的 RecyclerView(advanced and flexible version of ListView), 包括了下拉刷新, 加载更多, 多种动画, 空数据提示, 拖动排序, 视差处理, 工具栏渐变, 滑动删除, 自定义floating button, 多种刷新效果, scrollbar, sticky header, 多 layout 支持等等元素, 而且使用起来跟 RecyclerView 一样的方便 </td> 76. [MaterialEditText](https://github.com/rengwuxian/MaterialEditText) <td width="275"> MaterialEditText 是就职于 Flipboard 的员工 [扔物线](https://www.zhihu.com/people/rengwuxian) 开发的, 在 AppCompat v21 中也提供了 Material Design 的控件 EditText, 可是由于比较难用, 没有提供设置颜色的 Api, 于是就产生这个第三方库 </td> 77. [Side-Menu.Android](https://github.com/Yalantis/Side-Menu.Android) <td width="275"> Side Menu 是 [Yalantis](https://yalantis.com/) 组织开源出来, 该组织因开源出一些动画很棒的开源库为大家所熟知该库是其中一个, 该库是提供翻页动画效果的侧边菜单, 动画体验超赞的 </td> 78. [drag-sort-listview](https://github.com/bauerca/drag-sort-listview) <td width="275"> DragSortListView 是一个可以实现拖动排序, 滑动删除的 listview 控件, 注意的是作者对该库已经放弃维护更新了, 不过感兴趣的人可以去研究一下 </td> 79. [android-times-square](https://github.com/square/android-times-square) <td width="275"> TimesSquare 是 Square 公司出品的一款显示日历选择日期的控件, 可以让用户选择多个日期 </td> 80. [GreenDroid(不建议使用)](https://github.com/cyrilmottier/GreenDroid) <td width="275"> GreenDroid 是一个封装好的 Android UI 界面库, 不过该库已经被弃用了,不建议使用 </td> 81. [logger](https://github.com/orhanobut/logger) <td width="275"> Logger 是一个简单, 漂亮, 强大 Android 打印日志库 </td> 82. [acra](https://github.com/ACRA/acra) <td width="275"> Acra 是一个能够让 Android 应用自动将崩溃报告以谷歌文档电子表的形式进行发送的库, 旨在当应用发生崩溃或出现错误行为时, 开发者可以获取到相关数据 </td> 83. [FadingActionBar](https://github.com/ManuelPeinado/FadingActionBar) <td width="275"> FadingActionBar 是一个支持 ListView, ScrollView, WebView 向下滚动时逐渐显示 ActionBar 库 </td> 84. [AndroidImageSlider](https://github.com/daimajia/AndroidImageSlider) <td width="275"> AndroidImageSlider 库开发者是代码家, 该库是为 Banner 图片滑动提供多种动画效果, 还可以轻易为 Banner 加载网络图片 </td> 85. [SystemBarTint](https://github.com/jgilfelt/SystemBarTint) <td width="275"> SystemBarTint 是一个实现沉浸式状态栏库, 适用于 Android 系统 4.4 其以上的版本 </td> 86. [android-menudrawer](https://github.com/SimonVT/android-menudrawer) <td width="275"> MenuDrawer 是一款滑出式菜单库, 通过拖动屏幕边缘滑出菜单, 支持屏幕上下左右划出, 支持当前 View 处于上下层, 支持 Windows 边缘, ListView 边缘, ViewPager 变化划出菜单等 </td> 87. [RoundedImageView](https://github.com/vinc3m1/RoundedImageView) <td width="275"> RoundedImageView 一个快速支持图片圆角显示效果的库, 该库特点是能快速加载, 为了提高加载速度, 该库不用创建原始位图的副本, 不使用clipPath, 不使用 setXfermode 裁剪的位图等方式来实现 ImageView 圆角, 使用也非常简单 </td> 88. [afinal](https://github.com/yangfuhai/afinal) <td width="275"> Afinal 是一个 android 的 sqlite orm 和 ioc 框架, 同时封装了 android 中的 http 框架, 使其更加简单易用, 使用 finalBitmap, 无需考虑 bitmap 在 android 中加载的时候 oom 的问题和快速滑动的时候图片加载位置错位等问题, Afinal 的宗旨是简洁, 快速, 约定大于配置的方式, 尽量一行代码完成所有事情 </td> 89. [android-pulltorefresh(不建议使用)](https://github.com/johannilsson/android-pulltorefresh) <td width="275"> 另一个下拉刷新库, 但是该库已经停止维护, 因此不建议使用, 推荐使用 Android-Ultra-Pull-to-Refresh </td> 90. [Bolts-Android](https://github.com/BoltsFramework/Bolts-Android) <td width="275"> Bolts 是一款底层类库集合, 在后台实现异步操作, 并提供接口反馈当前异步执行的程度 (可以通过接口实现UI进度更新), 最后反馈执行的结果给UI主线程, 与AsyncTask比较: (1)使用的是无大小限制的线程池; (2)任务可组合可级联,防止了代码耦合 </td> 91. [NumberProgressBar](https://github.com/daimajia/NumberProgressBar) <td width="275"> NumberProgressBar 开发者是代码家, 这是一个带简约性感数字显示的进度条库, 使用非常简单方便 </td> 92. [SwipeBackLayout](https://github.com/ikew0ng/SwipeBackLayout) <td width="275"> SwipeBackLayout 是一个支持屏幕上下左右滑动返回上层 Activity, 关闭当前 Activity, 类似简书 App </td> 93. [android-gif-drawable](https://github.com/koral--/android-gif-drawable) <td width="275"> 一个支持 gif 显示的 view, 用 jni 实现的, 编译生成 so 库后直接 xml 定义 view 即可, 简单易用 </td> 94. [VitamioBundle](https://github.com/yixia/VitamioBundle) <td width="275"> Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架, 特点:(1) 全面支持硬件解码与 GPU 渲染, (2) 能够流畅播放 720P 甚至 1080P 高清 MKV, FLV, MP4, MOV, TS, RMVB 等常见格式的视频, (3) 在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP, HLS(m3u8)等常见的多种视频流媒体协议, 包括点播与直播 </td> 95. [SmartTabLayout](https://github.com/ogaclejapan/SmartTabLayout) <td width="275"> SmartTabLayout 是一个自定义的 Tab title strip, 基于 Google Samples 中的 android-SlidingTabBasic 项目, 滑动时 Indicator 可平滑过渡 </td> 96. [uCrop](https://github.com/Yalantis/uCrop) <td width="275"> uCrop 是[Yalantis](https://yalantis.com/) 组织开源的图片裁剪库, 支持缩放, 旋转图片, 支持各种比例的裁剪框, 非常强大的一个图片裁剪库 </td> 97. [android-crop](https://github.com/jdamcd/android-crop) <td width="275"> 又一个图片裁剪库, 向下兼容到 Api 10, 个人感觉这个库并没有比上面介绍的 uCrop 强大 </td> 98. [HoloEveryWhere](https://github.com/Prototik/HoloEverywhere) <td width="275"> HoloEveryWhere 是一套 Android 开发库, 提供了全套 Holo Style 控件, 它的外观与功能和标准 Holo Style 控件基本相同, 唯一不同的是它可以运行在低于 4.0 版本的 Android 系统上 </td> 99. [AVLoadingIndicatorView](https://github.com/81813780/AVLoadingIndicatorView) <td width="275"> AVLoadingIndicatorView 库含有各种各样漂亮的加载动画效果, 使用起来也非常简单, 和平时使用 ProgressBar 一样 </td> 00. [sweet-alert-dialog](https://github.com/pedant/sweet-alert-dialog) <td width="275"> Android 版的 SweetAlert, 清新文艺, 快意灵动的甜心弹框, 灵感来源于 JS 版[SweetAlert](http://t4t5.github.io/sweetalert/) </td> {#user-content-粗计.anchor}粗计 {#user-content-square-公司占有-7-席.anchor}Square 公司占有 7 席 项目名称 <th> 排名 </th> [Retrofit](https://github.com/square/retrofit) <td width="130"> 4 </td> [OkHttp](https://github.com/square/okhttp) <td width="130"> 5 </td> [Picasso](https://github.com/square/picasso) <td width="130"> 7 </td> [LeakCanary](https://github.com/square/leakcanary) <td width="130"> 13 </td> [Dagger](https://github.com/square/dagger) <td width="130"> 29 </td> [Otto](https://github.com/square/otto) <td width="130"> 44 </td> [TimesSquare](https://github.com/square/android-times-square) <td width="130"> 79 </td> {#user-content-facebook-公司占有-4-席.anchor}FaceBook 公司占有 4 席 项目名称 <th> 排名 </th> [React Native](https://github.com/facebook/react-native) <td width="124"> 1 </td> [Fresco](https://github.com/facebook/fresco) <td width="124"> 11 </td> [Stetho](https://github.com/facebook/stetho) <td width="124"> 38 </td> [Rebound](https://github.com/facebook/rebound) <td width="124"> 62 </td> {#user-content-jakewharton-大神占有-5-席.anchor}JakeWharton 大神占有 5 席 项目名称 <th> 排名 </th> [Butter Knife](https://github.com/JakeWharton/butterknife) <td width="98"> 14 </td> [ActionBarSherlock](https://github.com/JakeWharton/ActionBarSherlock) <td width="98"> 16 </td> [ViewPagerIndicator](https://github.com/JakeWharton/ViewPagerIndicator) <td width="98"> 18 </td> [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) <td width="98"> 55 </td> [Hugo](https://github.com/JakeWharton/hugo) <td width="98"> 73 </td> {#user-content-代码家大神占有-4-席.anchor}代码家大神占有 4 席 项目名称 <th> 排名 </th> [AndroidSwipeLayout](https://github.com/daimajia/AndroidSwipeLayout) <td width="89"> 28 </td> [AndroidViewAnimations](https://github.com/daimajia/AndroidViewAnimations) <td width="89"> 32 </td> [AndroidImageSlide](https://github.com/daimajia/AndroidImageSlider) <td width="89"> 84 </td> [NumberProgressBar](https://github.com/daimajia/NumberProgressBar) <td width="89"> 91 </td> 转自:http://www.lesscode.cn/index.php?s=/view-index-id-299.shtml ...

2016年3月15日 · 9 分钟 · 天边的星星

这可能是目前最鲁棒的Android声音录制和播放封装库了

安卓开发过程中一旦开始和硬件打交道,以及涉及到一定的native代码之后,各种闪退就开始浮出水面了,声音录制和播放当然不例外。本文总结了YOLO安卓客户端大半年来的安卓音频实践,整理出一套系统API的封装,命名为RxAndroidAudio。 概览 安卓平台和声音录制与播放相关的主要是4个类:MediaRecorder,MediaPlayer,AudioRecord和AudioTrack。 MediaRecorder可以录制视频和音频到文件,MediaPlayer可以播放视频和音频文件,AudioRecord可以提供接口读取音频流数据(byte数组或者short数组),AudioTrack提供接口用于播放音频流数据。 小结一下,其中MediaRecorder和AudioRecord用于声音录制,MediaPlayer和AudioTrack用于声音播放。AudioRecord和AudioTrack用于操作音频流数据,操作对象是byte数组(或者short数组),而MediaRecorder和MediaPlayer提供了经过更高层抽象和封装接口,直接对文件进行操作,而且他俩功能更丰富,同时支持音频和视频。 本文会涉及到部分关于声音录制和播放更底层的实现,详细的分析并不是本文的内容范围了,此外本文主要目标并不是声音录制和播放的使用教程,本文主要关注的是上述4个类的使用过程中需要注意的地方。 基于文件的操作 使用MediaRecorder录制声音到文件: mRecorder.prepare()调用需要捕获IOException和RuntimeException,注意需要捕获RuntimeException而不是IllegalStateException,尽管Java doc中只声明了会抛出IllegalStateException,但是查看jni层代码可以看到,prepare的调用也是可能会触发RuntimeException的; mRecorder.start(),mRecorder.stop(),mRecorder.reset()调用也需要捕获RuntimeException,理由同上; 无论是prepare还是start,抛出异常之后都需要reset和release; 需要保证不会对jni层进行多线程的调用,以免出现下面这样的“静默闪退”(参考资料),RxAndroidAudio通过单例和synchronized方法来保证这一点: A/libc: Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 9302 (RxComputationTh) 当用户录完声音,需要停止录音,调用stop的时候,需要sleep一段时间,以免最后几百毫秒录不上,这有可能是安卓系统音频编码器的bug,参考资料; 当prepare返回后,有些低端的设备需要再延迟一段时间开始说话,以免开头几百毫秒录不上,可以在prepare返回后延迟几百毫秒(例如300ms)再显示初始化完毕的UI,原因还需要继续寻找; 使用MediaPlayer播放声音文件: 和MediaRecorder一样,prepare,start,stop,reset,release函数的调用都需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; MediaPlayer提供了两种音频文件播放方式:通过文件绝对路径指定播放文件,或者使用资源文件id指定;绝对路径的方式需要调用mPlayer.prepare(),而资源文件id方式不需要; 在MediaPlayer.OnCompletionListener的onCompletion回调中,需要延迟一定时间再释放MediaPlayer,否则可能导致下次紧接着的播放无法成功(静默失败,不会抛出异常),原因还需要继续寻找; 基于数据流的操作 使用AudioRecord录制音频流数据: 和MediaRecorder一样,startRecording需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; mAudioRecord.read的返回值需要进行错误检查; mAudioRecord.read传入的参数类型需要进行区分,ENCODING_PCM_16BIT格式的录音需要传入short数组,ENCODING_PCM_8BIT格式的录音需要传入byte数组,尽管在jni层的实现都是一样的,但是[Java doc][18]明确说明了这一注意事项,理应遵循; RxAndroidAudio使用ExecutorService来执行异步任务(从AudioRecord中循环读取数据); [使用AudioTrack播放音频流数据][19]: 和MediaRecorder一样,write需要捕获异常; 和MediaRecorder一样,需要保证不会对jni层进行多线程的调用; Bonus Part Reactive! RxAndroidAudio之所以叫Rx,就是因为它尽可能的提供了Reactive的API。 RxAudioPlayer播放声音文件: 当然RxAudioPlayer也提供了传统的API: RxAmplitude获取当前说话音量等级: 当然RxAmplitude使用的是AudioRecorder的传统API: [18]: http://developer.android.com/reference/android/media/AudioRecord.html#read(byte[], int, int) [19]: https://github.com/Piasy/RxAndroidAudio/blob/master/rxandroidaudio%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgithub%2Fpiasy%2Frxandroidaudio%2FStreamAudioPlayer.java

2016年2月26日 · 1 分钟 · 天边的星星

国内镜像加速Android源码下载

转发:http://www.tuicool.com/articles/nmy26nv 清华大学镜像 无论是Ubuntu源更新还是Android源码下砸,都是使用清华大学镜像。 Ubuntu源使用方法 不多说了,不会的自行Google。 Android源码清华镜像使用方法 官方介绍使用方法 ==== 点击浏览 ==== 我来介绍 1.下载修改好的 repo , ==== 下载地址 ====,密码: rb5t ; 2.打开终端,输入: ``` mkdir ~/bin PATH=~/bin:$PATH </div> </div> 3.将 **repo** 放入 `~/bin` 目录下; 4.赋予执行权限,终端输入: <div> <div> ``` chmod a+x ~<span class="regexp">/bin/repo</span> 5.建立android源码存放目录: ``` mkdir android_source cd android_source </div> </div> 6.查看想要下载的源码的Tag和Builds,网址: [==== **点击查看,需要翻蔷** ====](https://source.android.com/source/build-numbers.html#source-code-tags-and-builds),这里 @安卓猴 给你们截下图,自己放大查看: ![](http://img1.tuicool.com/bMBn2eu.jpg!web) 7.例如我要下载android-5.1.1_r3,就在终端输入: <div> <div> ``` repo init -u <span class="symbol">git:</span>/<span class="regexp">/aosp.tuna.tsinghua.edu.cn/android</span><span class="regexp">/platform/manifest</span> -b android-<span class="number">5.1</span>.<span class="number">1_</span>r3 8.终端输入下面命令使用 repo 开始源代码下载同步, -j4 表示并发数为4,清华镜像只支持最大并发数4: ...

2016年2月21日 · 1 分钟 · 天边的星星

Android 自定义控件——图片剪裁

该控件由另一篇文章:Android 图片拖拽、放大缩小的自定义控件 扩展而来 http://www.linuxidc.com/Linux/2014-12/110763.htm 如图: 思路:在一个自定义View上绘制一张图片(参照前面提到的另一篇文章),在该自定义View上绘制一个自定义的FloatDrawable,也就是图中的浮层。绘制图片和FloatDrawable的交集的补集部分灰色阴影(这个其实很简单,就一句话)。在自定义View的touch中去处理具体的拖动事件和FloatDrawable的变换。图片的绘制和FloatDrawable的绘制以及变换最终其实就是在操作各自的Rect而已,Rect就是一个有矩形,有四个坐标,图片和FloatDrawable就是按照坐标去绘制的。 CropImageView.java 该类继承View 功能:在onDraw方法中画图片、浮层,处理touch事件,最后根据坐标对图片进行剪裁。 public class CropImageView extends View { // 在touch重要用到的点, private float mX_1 = 0; private float mY_1 = 0; // 触摸事件判断 private final int STATUS_SINGLE = 1; private final int STATUS_MULTI_START = 2; private final int STATUS_MULTI_TOUCHING = 3; // 当前状态 private int mStatus = STATUS_SINGLE; // 默认裁剪的宽高 private int cropWidth; private int cropHeight; // 浮层Drawable的四个点 private final int EDGE_LT = 1; private final int EDGE_RT = 2; private final int EDGE_LB = 3; private final int EDGE_RB = 4; private final int EDGE_MOVE_IN = 5; private final int EDGE_MOVE_OUT = 6; private final int EDGE_NONE = 7; ...

2016年2月19日 · 7 分钟 · 天边的星星