How to create simple view separators

介绍

这将向您展示两种方法可以创建漂亮的分隔符,例如一排按钮之间使用。

(https://raw.githubusercontent.com/ITBox/Picture/master/buttons-with-separators3.png)

方法1 手动添加一个视图分离器LinearLayout

作为一个分隔符,我们可以使用一个视图如下:

<View
   android:layout_height="fill_parent"
   android:layout_width="1dp"
   android:background="#90909090"
   android:layout_marginBottom="5dp"
   android:layout_marginTop="5dp"
/>

整个布局,如图所示,就变成:

 <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:orientation="horizontal">

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"Yes"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button1"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;View</span> <span class="na">android:layout_height=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_width=</span><span class="s">"1px"</span>
    <span class="na">android:background=</span><span class="s">"#90909090"</span>
    <span class="na">android:layout_marginBottom=</span><span class="s">"5dp"</span>
    <span class="na">android:layout_marginTop=</span><span class="s">"5dp"</span>
    <span class="na">android:id=</span><span class="s">"@+id/separator1"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"No"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button2"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;View</span> <span class="na">android:layout_height=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_width=</span><span class="s">"1px"</span>
    <span class="na">android:background=</span><span class="s">"#90909090"</span>
    <span class="na">android:layout_marginBottom=</span><span class="s">"5dp"</span>
    <span class="na">android:layout_marginTop=</span><span class="s">"5dp"</span>
    <span class="na">android:id=</span><span class="s">"@+id/separator2"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"Neutral"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button3"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

</LinearLayout>

方法2 指定一个分压器LinearLayout

您可以指定一个视图linearlayout分配器。这显然是一个更好的解决方案(和我寻找的解决方案),还可以锻炼当你处理一个未知数量的Items。 这种方法只适用于API 11和更高的水平。 * 创建一个叫separator.xml的drawable文件:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
   <size android:width="1dp" />
   <solid android:color="#90909090" />
</shape>

  • 我们可以这样在布局中用

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:divider="@drawable/separator"
    android:showDividers="middle"
    android:orientation="horizontal">

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"Yes"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button1"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"No"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button2"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

<span class="nt">&lt;Button</span>
    <span class="na">android:layout_width=</span><span class="s">"fill_parent"</span>
    <span class="na">android:layout_height=</span><span class="s">"wrap_content"</span>
    <span class="na">style=</span><span class="s">"?android:attr/buttonBarButtonStyle"</span>
    <span class="na">android:text=</span><span class="s">"Neutral"</span>
    <span class="na">android:layout_weight=</span><span class="s">"1"</span>
    <span class="na">android:id=</span><span class="s">"@+id/button3"</span>
    <span class="na">android:textColor=</span><span class="s">"#00b0e4"</span> <span class="nt">/&gt;</span>

</LinearLayout>

这里的重要部分是:

      android:divider="@drawable/separator"
      android:showDividers="middle"

TextView开源

NineOldAndroids动画库

介绍

Android3.0推出了全新的AnimationAPI,使用起来很方便,但是不能在3.0以下版本使用,NineOldAndroids是一个可以在任意Android版本上使用的AnimationAPI,API和Android3.0中的类似。

常用类

  • ObjectAnimator
  • ValueAnimator
  • AnimatorSet
  • ViewPropertyAnimator

类名与官方的API是对应的,只是包名为com.nineoldandroids.animation

使用方法

首先导入NineOldAndroids的jar包。在Android3.0中,View中有一个animate方法,NineOldAndroids中提供了ViewPropertyAnimator.animate(View)与其对应,可以选择静态导入。

// 官方API(3.0以上)
mView.animate().setDuration(5000).rotationY(720).x(100).y(100).start();

// NineOldAndroids ViewPropertyAnimator.animate(mView).setDuration(5000) .rotationY(720).x(100).y(100).start();

// 可以使用静态导入 import static com.nineoldandroids.view.ViewPropertyAnimator.animate; // 直接调用animate方法 animate(mView).setDuration(5000).rotationY(720).x(100).y(100).start();

使用链式编程设置各种属性参数,最终调用start()来启动动画,还可以调用setStartDelay()设置动画延迟启动。

可以设置动画的监听器,在动画开始、结束等时候加一些处理。

ViewPropertyAnimator
    .animate(mIView)
    .setDuration(5000)
    .rotationY(720)
    .x(100).y(100)
    .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            super.onAnimationStart(animation);
            // 动画开始
        }
        @Override
        public void onAnimationCancel(Animator animation) {
            super.onAnimationCancel(animation);
            // 动画取消
        }
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            // 动画结束
        }
        @Override
        public void onAnimationRepeat(Animator animation) {
            super.onAnimationRepeat(animation);
            // 动画重复启动
        }
    }).start();

ViewPropertyAnimator对象提供了取消动画的方法

ViewPropertyAnimator animate = ViewPropertyAnimator.animate(mDropTv);
/ ... /
animate.start();   // 开始动画
animate.cancel();  // 取消动画

简单的动画效果使用ViewPropertyAnimator一般可以满足,下面介绍一下高级玩法。核心是ObjectAnimator类。

举例

ValueAnimator colorAnim = ObjectAnimator.ofInt(mView, "backgroundColor", /红色/0xFFFF8080, /蓝色/0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());  // ARGB
colorAnim.setRepeatCount(ValueAnimator.INFINITE);   // 无限重复
colorAnim.setRepeatMode(ValueAnimator.REVERSE); // 反转回去
colorAnim.start();

AnimatorSet set = new AnimatorSet();
set.playTogether(
    ObjectAnimator.ofFloat(myView, "rotationX", 0, 360),
    ObjectAnimator.ofFloat(myView, "rotationY", 0, 180),
    ObjectAnimator.ofFloat(myView, "rotation", 0, -90),
    ObjectAnimator.ofFloat(myView, "translationX", 0, 90),
    ObjectAnimator.ofFloat(myView, "translationY", 0, 90),
    ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f),
    ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f),
    ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1)
);
set.setDuration(5 * 1000).start();

AnimatorSet主要方法有两个,playSequentially 是创建按顺序执行的动画,playTogether是创建同时执行的动画。

ObjectAnimator说明

ObjectAnimator是动画对象,通过ObjectAnimator提供的一系列of开头的静态方法创建。

创建一般需要传入三个参数

  • target,Object类型,可不是View哦
  • PropertyName,String类型或Property类型,用于描述target中的属性
  • 数组,ofInt()就是int数组

ObjectAnimator原理是这样的:会调用targetset方法,设置PropertyName的值,这个值的计算方式是,根据Duration时长和第三个参数数组来计算出来当前时间的值。然后调用set方法设置进去。例如上面更改背景颜色的实例PropertyNamebackgroundColor,数组是两个颜色值,运行动画就会根据Duration计算当前的颜色值,调用targetsetBackgroundColor方法设置进去,从而改变了背景颜色。

再看改AnimatorSet的实例PropertyNamerotationXtranslationX之类的,这几个属性是在Android3.0以上才有的,所以调用set方法会出错的,通过观察ObjectAnimator,发现对这几个属性做了特殊处理,提前预制了这几个属性值。

static {
        PROXY_PROPERTIES.put("alpha", PreHoneycombCompat.ALPHA);
        PROXY_PROPERTIES.put("pivotX", PreHoneycombCompat.PIVOT_X);
        PROXY_PROPERTIES.put("pivotY", PreHoneycombCompat.PIVOT_Y);
        PROXY_PROPERTIES.put("translationX", PreHoneycombCompat.TRANSLATION_X);
        PROXY_PROPERTIES.put("translationY", PreHoneycombCompat.TRANSLATION_Y);
        PROXY_PROPERTIES.put("rotation", PreHoneycombCompat.ROTATION);
        PROXY_PROPERTIES.put("rotationX", PreHoneycombCompat.ROTATION_X);
        PROXY_PROPERTIES.put("rotationY", PreHoneycombCompat.ROTATION_Y);
        PROXY_PROPERTIES.put("scaleX", PreHoneycombCompat.SCALE_X);
        PROXY_PROPERTIES.put("scaleY", PreHoneycombCompat.SCALE_Y);
        PROXY_PROPERTIES.put("scrollX", PreHoneycombCompat.SCROLL_X);
        PROXY_PROPERTIES.put("scrollY", PreHoneycombCompat.SCROLL_Y);
        PROXY_PROPERTIES.put("x", PreHoneycombCompat.X);
        PROXY_PROPERTIES.put("y", PreHoneycombCompat.Y);
    }

总结

NineOldAndroids的API与官方的API基本一致,使用很方便。能够轻松实现各种酷炫动画效果。

  • 一般情况使用ViewPropertyAnimator就可以了,可以设置动画监听器,实现连贯动画,和其他处理。
  • ObjectAnimator创建的targetObject,可以传入任何对象,原理是调用set方法,利用这个特性可以实现很多自定义的效果有点和Scroller类似。

参考

如何修改jar文件的包名

首先我们要说说为什么要修改jar文件的包名,jar包我们会非常高频率的使用,尤其是用一些其他三方库的时候,往往把java代码打包成jar文件,方便项目依赖使用。笔者在开发过程中遇到过一些问题,是由于jar文件里面的包名和项目或者运行时环境的引用文件包名上存在冲突导致的,这时候我们修改jar文件的包名是一个比较快速有效的解决办法。举两个例子,是笔者亲身经历的两个情况。

  • Gson库:这个相信很多人都在使用,但是直接导入gson的jar包,在HTC Desire HD这款手机上会抛出异常(TypeNotFoundException)
  • Jackson库:这也是个json解析的,我们在做苹果推送后台的时候,后台用java写的,使用java-apns库,依赖于Jackson,然后运行就会抛出异常,具体原因没有查,初步怀疑包名冲突,修改之后就解决的。

下面介绍如何修改jar文件的包名,需要用到一个小工具,叫做jarjar.jar

这里我们以gson.jar为例,在gson.jar包目录下新建一个文本文件,名字随意,例如rule.txt,写入下面的内容。

rule com.google.gson.** com.google.mygson.@1

上面写的就是修改规则,我们将包名中的gson修改为mygson。打开命令行,输入如下命令。

java -jar jarjar.jar process rule.txt gson.jar mygson.jar

命令执行完毕,同目录下会多出一下mygson.jar,这个就是修改包名之后的jar文件,我们项目导入这个jar包使用即可。

Eclipse ADT 中 libs jar 包关联源代码 和 javadoc

一. 操作如下

  • 把库的 .jar 文件放到 libs 目录中,对应的 source .jar (或者 doc .jar)文件放到和 libs 同级的 libs-src 目录(可以为其他任意目录,但是不要放到 libs 目录中)。
  • 在libs 目录中创建一个 .properties 文件,该文件的名字为 .jar 库的名字加上 .properties 后缀。例如 butterknife-4.0.1.jar 对应的 .properties 名字为 butterknife-4.0.1.jar.properties
  • 在 .properties 文件中设置 sources 和 javadoc .jar 包的路径。
  • 关闭 并重新打开该 Android 项目!如果不可关联代码可以尝试用 F5 刷新下项目文件或者重启 eclipse。

更详细的过程和截图可以参考这里

Android自动滚动轮播循环的ViewPager

代码下载地址

简单的通过handler发送消息去完成一次滚动,在完成一次滚动后发送另外一个delay的滚动消息,如此循环实现。

一. 如何使用

  • (1) <自己的包名.AutoScrollViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="wrap_content" />
  • (2) AutoScrollViewPager viewPager = (AutoScrollViewPager)findViewById(R.id.view_pager); viewPager.setAdapter(new ImagePagerAdapter(context, imageIdList)); viewPager.setOnPageChangeListener(new MyOnPageChangeListener());// 可以放自己的小圆点或字样 implements OnPageChangeListener viewPager.setInterval(2000); viewPager.startAutoScroll();

二. 属性介绍

  • startAutoScroll() 启动自动滚动 stopAutoScroll() 停止自动滚动 setInterval(long) 设置自动滚动的间隔时间,单位为毫秒 setDirection(int) 设置自动滚动的方向,默认向右 setCycle(boolean) 是否自动循环轮播,默认为true setScrollDurationFactor(double) 设置ViewPager滑动动画间隔时间的倍率,达到减慢动画或改变动画速度的效果 setStopScrollWhenTouch(boolean) 当手指碰到ViewPager时是否停止自动滚动,默认为true setSlideBorderMode(int) 滑动到第一个或最后一个Item的处理方式,支持没有任何操作、轮播以及传递到父View三种模式 setBorderAnimation(boolean) 设置循环滚动时滑动到从边缘滚动到下一个是否需要动画,默认为true

HoloEverywhere

HoloEverywhere是一个能够让我们在2.1+的系统上实现Android4.0的Holo风格。

下面是我在Android2.3.7上运行的HoloEverywhere示例的几张截图:

HoloEverywhere使用

HoloEverywhere中集成了android-support-v7-appcompat包,所以在低版本使用actionbar不需要引用任何包。

使用HoloEverywhere只需要以下简单步骤:

  1. 所有的Activity继承org.holoeverywhere.app.***Activity
  2. 所有的Fragment继承org.holoeverywhere.app.***Fragment
  3. 为清单文件标签添加android:name="org.holoeverywhere.app.Application",或者自定义Application继承org.holoeverywhere.app.Application。
  4. 使用org.holoeverywhere.widget包下的控件替代Android原生的控件。 GitHub下载