Android FlipLayout

这周新功能有一个类似web版Google+翻转的特效,Android自带的动画效果全是基于平面的,像实现这种3D效果必须要自定义,于是自己写了个demo。效果如下:

主要思路其实也蛮简单的,主要是自定义一个Animation,然后在applyTransformation方法里通过矩阵变换让其按照y轴旋转,只是在旋转到中间画面的切换细节稍微处理下。

使用

用法非常简单,可以直接在xml中使用,类似下面:

<?xml version="1.0" encoding="utf-8"?>
<com.storm.fliplayout.lib.FlipLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/flipLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="@string/front"
        android:textAppearance="@android:style/TextAppearance.Large" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:background="#FF999999"
        android:gravity="center"
        android:text="@string/back"
        android:textAppearance="@android:style/TextAppearance.Large"
        android:visibility="gone" />

</com.storm.fliplayout.lib.FlipLayout>

当然使用中不仅限于TextView,你同样可以放很负责的布局进去,但是要注意保证FlipLayout只有两个child。

github地址:FlipLayout


Android SwipeRefreshLayout

今天在Google+上看到了SwipeRefreshLayout这个名词,遂搜索了下,发现竟然是刚刚google更新sdk新增加的一个widget,于是赶紧抢先体验学习下。

SwipeRefreshLayout

SwipeRefreshLayout字面意思就是下拉刷新的布局,继承自ViewGroup,在support v4兼容包下,但必须把你的support library的版本升级到19.1。 提到下拉刷新大家一定对ActionBarPullToRefresh比较熟悉,而如今google推出了更官方的下拉刷新组件,这无疑是对开发者来说比较好的消息。利用这个组件可以很方便的实现Google Now的刷新效果,见下图:

主要方法

  • setOnRefreshListener(OnRefreshListener): 为布局添加一个Listener

  • setRefreshing(boolean): 显示或隐藏刷新进度条

  • isRefreshing(): 检查是否处于刷新状态

  • setColorScheme(): 设置进度条的颜色主题,最多能设置四种

xml布局文件

布局文件很简单,只需要在最外层加上SwipeRefreshLayout,然后他的child是可滚动的view即可,如ScrollView或者ListView。如:

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
 
        <TextView
            android:text="@string/hello_world"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:gravity="center"/>
    </ScrollView>
 
</android.support.v4.widget.SwipeRefreshLayout>

Activity代码

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    swipeLayout.setOnRefreshListener(this);
    swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
            android.R.color.holo_green_light, 
            android.R.color.holo_orange_light, 
            android.R.color.holo_red_light);
}
 
public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override public void run() {
            swipeLayout.setRefreshing(false);
        }
    }, 5000);
}

上面的代码很简单,只需要给SwipeRefreshLayout添加一个listener,值得说明的是setColorScheme方法是设置刷新进度条的颜色,最多只能设置4种循环显示,默认第一个是随用户手势加载的颜色进度条。

源码

写了的小demo在github上,地址在:SwipeRefreshLayoutDemo

总结

google在不断完善自己的sdk,推出越来越多的组件,其目的是让开发更简单,设计上更统一,这可能是google未来的方向,不管怎样,这对开发者来说无疑是非常好的消息。


Android WebView播放视频问题

此次的方案用到WebView,而且其中会有视频嵌套,在默认的WebView中直接播放视频会有问题,而且不同的SDK版本情况还不一样,网上搜索了下解决方案,在此记录下.

webView.getSettings.setPluginState(PluginState.ON);
webView.setWebChromeClient(new WebChromeClient());

然后在webView的Activity配置里面加上:

android:hardwareAccelerated="true"

以上可以正常播放视频了,但是webview的页面都finish了居然还能听到视频播放的声音,于是又查了下发现webview的 onResume方法可以继续播放,onPause可以暂停播放, 但是这两个方法都是在Added in API level 11添加的,所以需要用反射来完成。

停止播放:在页面的onPause方法中使用:

webView.getClass().getMethod("onPause").invoke(webView,(Object[])null);

继续播放:在页面的onResume方法中使用:

webView.getClass().getMethod("onResume").invoke(webView,(Object[])null);

这样就可以控制视频的暂停和继续播放了。


Best Practices for Using Alpha

Alpha是图形界面开发中常用的特效,通常我们会使用以下代码来实现Alpha特效:

view.setAlpha(0.5f);
View.ALPHA.set(view, 0.5f);
ObjectAnimator.ofFloat(view, "alpha", 0.5f).start();
view.animate().alpha(0.5f).start();
view.setAnimation(new AlphaAnimation(1.0f, 0.5f));

其效果都等同于:

canvas.saveLayer(l, r, t, b, 127, Canvas.CLIP_TO_LAYER_SAVE_FLAG);

所以常见的alpha特效是通过将图像绘制到offscreen buffer中然后显示出来,这样的操作是非常消耗资源的,甚至可能导致性能问题,在开发过程中我们可以通过其他方式避免创建offsreen buffer。

TextView

对于TextView我们通常需要文字透明效果,而不是View本身透明,所以,直接设置带有alpha值的TextColor是比较高效的方式。

// Not this
textView.setAlpha(alpha);

// 以下方式可以避免创建 offscreen buffer
int newTextColor = (int) (0xFF * alpha) << 24 | baseTextColor & 0xFFFFFF;
textView.setTextColor(newTextColor);

ImageView

同样的对于只具有src image的ImageView,直接调用setImageAlpha()方法更为合理。

// Not this, setAlpha方法由View继承而来,性能不佳
imageView.setAlpha(0.5f);

// 使用以下方式时,ImageView会在绘制图片时单独为图片指定Alpha
// 可以避免创建 offScreenBuffer
imageView.setImageAlpha((int) alpha * 255);

CustomView

类似的,自定义控件时,应该直接去设置paint的alpha。

// Not this
customView.setAlpha(alpha);

// But this
paint.setAlpha((int) alpha * 255);
canvas.draw*(..., paint);

同时Android提供了hasOverlappingRendering()接口,通过重写该接口可以告知系统当前View是否存在内容重叠的情况,帮助系统优化绘制流程,原理是这样的:对于有重叠内容的View,系统简单粗暴的使用 offscreen buffer来协助处理。当告知系统该View无重叠内容时,系统会分别使用合适的alpha值绘制每一层。

/**
 * Returns whether this View has content which overlaps. This function, intended to be
 * overridden by specific View types, is an optimization when alpha is set on a view. If
 * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
 * and then composited it into place, which can be expensive. If the view has no overlapping
 * rendering, the view can draw each primitive with the appropriate alpha value directly.
 * An example of overlapping rendering is a TextView with a background image, such as a
 * Button. An example of non-overlapping rendering is a TextView with no background, or
 * an ImageView with only the foreground image. The default implementation returns true;
 * subclasses should override if they have cases which can be optimized.
 *
 * @return true if the content in this view might overlap, false otherwise.
 */
public boolean hasOverlappingRendering() {
    return true;
}

最后引用Chet Haase的一句话作为总结

“You know what your view is doing, so do the right thing for your situation.”

Via Android Tips: Best Practices for Using Alpha


我理想的工作环境

做开发也有些时日了,貌似每个工程师心中都有个理想的工作环境,那么就来说说我心中理想的工作环境吧。首先声明个人是做Android开发。

硬件环境

  • RMBP + Dell 23寸显示器

双屏貌似是程序员必备,个人认为Dell的23寸刚好不错。至于RMBP则是工程师们的最爱,用过Mac感觉不会再用别的电脑了。类Unix的OS X系统完全兼容大多数开发软件,强大的硬件配置让你不用担心性能问题,反正自从用了Mac,很少碰到Windows上的卡顿问题了。

  • Nexus 5

做Android开发怎能没有一个像样的手机,要论目前最好的Android手机是什么,那毫无疑问应该是Google的5儿子。从硬件配置到使用体验都没得说,用了N5我想说再也不想用其他手机了。要实在说缺点的话就是耗电量大了点,但这应该是智能手机的通病了把。

软件环境

  • Android Studio + Gradle

Android Studio绝对是Android开发的未来,各种功能都很棒,可能唯一的不足是现在还不太成熟,而且从Eclipse迁移过来各种不习惯,但你要坚信这是未来,所以早点学习上手总不是坏处。至于用Gradle来自动编译、管理依赖非常简单方便,这篇博客则介绍了如何使用Gradle。Android Gradle

  • Git

目前用Git来做版本控制应该都没得说吧,但在分支的管理上更习惯用GitFlow,这里有一篇博客介绍了GitFLow—使用Git Flow管理开发流程

  • MarkDown

个人推荐程序员写文档必须用MarkDown格式,语法简单方便,兼容Html,如果用Word不是觉得太低级了么!

  • Sublime Text

除了IDE之外这个算是最常用的编辑器了,很棒!当然你可能是vim粉,那就略过此条吧!

  • iTerm

个人觉得应该是Mac下最好用的命令行工具了吧!

  • OmniGraffle

Mac上比较好用的画图工具,可以画出非常棒的流程图,类图。

  • Remote

还有什么比支持远程工作更兴奋的事么?

当然可能还有一些很棒且常用的软件如Chrome, Source Tree, Dash, PS, Axure等等,自己理想的开发环境就差不多这样了,最后如果你是土豪,那怎能不给自己配备一个高大上的人体工学椅呢?