Android进阶-Android 5.X 的新特性

虽然Android 8.0都出了,但是Android 5.X还是需要学习的,这个版本有很多动画还是很好看的,学习了可以提高用户体验的,这也是进阶的一个阶梯

1、Android 5.X UI设计初步

Android 5.X系列开始使用新的设计风格Material Design来统一整个Android系统的界面设计风格。

1.1、材料的形态模拟

材料的心态模拟是Material Design中最核心也是改变最大的一个设计,Google通过模拟自然界纸墨的形态变化、光线和阴影、纸与纸之间的控件层级关系,带来一种真实的空间感。
这里写图片描述

1.2、更加真实的动画

Android 5.X中大量加入了各种新的动画效果,让整个设计风格更加自然、和谐。
这里写图片描述

1.3、大色块的使用

Material Design中用大量高饱和度、始终亮度的大色块来突出界面的主次,并一扫Android4.X系列Holo主体的沉重感,让界面更加富有时尚感和视觉冲击力。
这里写图片描述
此外,Google在其Design网站上,有整个Material Design的设计Spec网站:
https://www.google.com/design/#resources




2、Material Design主题

Material Design现在又三种默认的主题可以设置:

  • @android:style/Theme.Material (dark version)

  • @android:style/Theme.Material.Light (light version)

  • @android:style/Theme.Material.Light.DarkActionBar

这里写图片描述

同时Android 5.X提出了Color Palette的概念,让开发者可以自己设定系统区域的颜色,使整个App的颜色风格和系统的颜色风格保持一致。

这里写图片描述

通过如下所示的代码,可以通过使用自定义Style的方式来创建自己的Color Palette颜色主题,从而实现不同的颜色风格

<resources>
    <!-- inherit from the material theme-->
    <style name="AppTheme" parent="android:Theme.Material">
        <!-- Main theme color-->
        <!-- your app branding color for the app bar-->
        <item name="colorPrimary">#BEBEBE</item>
        <!-- derker variant for thr status bar and contextual app bars-->
        <item name="colorPrimaryDark">#FF5AEBFF</item>
        <!--theme ui controls like checkBoxs and text fields-->
        <item name="colorAccent">#FFFF4130</item>
    </style>
</resources>

运行结果:

这里写图片描述




3、Palette

Android 5.X创新的使用Palette来提取颜色,从而让主题能够动态适应当前页面的色调
Android内置了几种提取色调的种类:

  • Vibrant(充满活力的)
  • Vibrant dark(充满活力的黑)
  • Vibrant light(充满活力的白)
  • Muted(柔和的)
  • Muted dark(柔和的黑)
  • Muted light(柔和的白)

使用Palette需要在Dependencies选项卡中添加以下的依赖:

compile 'com.android.support:palette-v7:21.0.2'

可以通过传递一个Bitmap对象给Palette,并调用它的Palette.generate()静态方法或者Palette.generateAsync()方法来创建一个Palette。

下面演示如何通过加载图片的柔和色调来改变状态栏和Actionbar的色调:

public class PaletteActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_palette);
         Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
                    R.drawable.test);
            // 创建Palette对象
            Palette.generateAsync(bitmap,
                    new Palette.PaletteAsyncListener() {
                        @Override
                        public void onGenerated(Palette palette) {
                            // 通过Palette来获取对应的色调
                            Palette.Swatch vibrant =
                                    palette.getDarkVibrantSwatch();
                            // 将颜色设置给相应的组件
                            getActionBar().setBackgroundDrawable(
                                    new ColorDrawable(vibrant.getRgb()));
                            Window window = getWindow();
                            window.setStatusBarColor(vibrant.getRgb());
                        }
                    });
    }
}

运行结果:

这里写图片描述




4、视图与阴影

Material Design的一个很重要的特点就是拟扁平化。通过展现生活中的材质效果、恰当地使用阴影和光线,配合完美的动画效果,模拟出一个动感十足又没理大胆的视觉效果。

4.1、阴影效果

以往的Android View只有两个属性—X和Y,而在Android 5.X中Google为其增加了一个新的属性—Z,而View中的Z值由两部分组成:

Z = elevation + translationZ;

通常在xml布局中静态设置View 的视图高度:

android:elevation="XXdp"

通过下面的代码演示不同视图高度所显示效果的不同:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.elevation.ElevationActivity" >

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        android:background="@drawable/ic_launcher" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        android:background="@drawable/ic_launcher"
        android:elevation="1dp" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_margin="10dp"
        android:background="@drawable/ic_launcher"
        android:elevation="20dp" />

</LinearLayout>

运行结果:
这里写图片描述

在程序中,同样可以使用如下代码来动态改变试图高度:

view.setTranslationZ(xxx);

通常也会使用属性动画来为视图高度改变的时候增加一个动画效果:

if(flag){
    view.animate().translationZ(100);
    flag = false;
}else {
    view.animate().translationZ(0);
    flag = true;
}




5、Tinting和Clipping

Android 5.X在堆图像的操作上有了更多的功能,下面来看看Android 5.X的两个队操作图像的新功能—Tinting(着色)和Clipping(裁剪)

5.1、Tinting(着色)

Tinting的使用非常简单,只要在XML中配置好tint和tintMode就可以了。下面例子设置了几种不同的tint和tintMode来演示Tinting效果:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.MainActivity" >

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:elevation="5dp"
        android:src="@drawable/ic_launcher" />

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:elevation="5dp"
        android:src="@drawable/ic_launcher"
        android:tint="@android:color/holo_blue_bright" />

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:elevation="5dp"
        android:src="@drawable/ic_launcher"
        android:tint="@android:color/holo_blue_bright"
        android:tintMode="add" />

    <ImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:elevation="5dp"
        android:src="@drawable/ic_launcher"
        android:tint="@android:color/holo_blue_bright"
        android:tintMode="multiply" />

</LinearLayout>

运行结果:
这里写图片描述

5.2、Clipping(裁剪)

Clipping可以让我们改变一个视图的外形。要使用Clipping,首先需要使用ViewOutlineProvider来修改outLine,然后再通过setOutlineProvider将outLine作用给视图。

下面通过例子来理解Clipping的使用思路:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context="com.itman.androidfive.MainActivity" >

    <TextView
        android:id="@+id/tv_rect"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="20dp"
        android:elevation="1dp"
        android:gravity="center" />

    <TextView
        android:id="@+id/tv_circle"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="20dp"
        android:elevation="1dp"
        android:gravity="center" />

</LinearLayout>

程序代码中:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View v1 = findViewById(R.id.tv_rect);
        View v2 = findViewById(R.id.tv_circle);
        //获取Outline
        ViewOutlineProvider viewOutlineProvider1 = new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //修改outline为特定形状
                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 30);
            }
        };
        //获取Outline
        ViewOutlineProvider viewOutlineProvider2 = new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //修改outline为特定形状
                outline.setOval(0, 0, view.getWidth(), view.getHeight());
            }
        };
        //重新设置形状
        v1.setOutlineProvider(viewOutlineProvider1);
        v2.setOutlineProvider(viewOutlineProvider2);
    }
}

运行结果:
这里写图片描述




6、列表与卡片


6.1、RecyclerView

RecyclerView就是ListView的升级,使用起来更方便,效率更高。
要使用RecyclerView就需要在Dependencies选项卡中添加以下的依赖,或者下个v7的recyclerview的jar包:

compile 'com.android.support:recyclerview-v7:21.0.2'

准备一个适配器:

public class RecyclerAdapter extends
        RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

    private List<String> mData;

    public RecyclerAdapter(List<String> data) {
        mData = data;
    }

    public OnItemClickListener itemClickListener;

    public void setOnItemClickListener(OnItemClickListener itemClickListener) {
        this.itemClickListener = itemClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements
            View.OnClickListener {

        public TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView;
            textView.setOnClickListener(this);
        }

        // 通过接口回调来实现RecyclerView的点击事件
        @Override
        public void onClick(View v) {
            if (itemClickListener != null) {
                itemClickListener.onItemClick(v, getPosition());
            }
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        // 将布局转化为View并传递给RecyclerView封装好的ViewHolder
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(
                R.layout.rc_item, viewGroup, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        // 建立起ViewHolder中视图与数据的关联
        viewHolder.textView.setText(mData.get(i) + i);
    }

    @Override
    public int getItemCount() {
        return mData.size();
    }
}

item的布局:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:text="111"
    android:textSize="40sp"
    android:gravity="center"
    android:layout_width="match_parent"
    android:background="#bebebe"
    android:layout_margin="3dp"
    android:layout_height="match_parent">

</TextView>

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.recyclerview.RecyclerActivity" >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rc_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"
        android:scrollbars="vertical" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <Spinner
            android:id="@+id/spinner"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:entries="@array/recycler_list" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="addRecycler"
            android:text="Add" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="delRecycler"
            android:text="Del" />
    </LinearLayout>

</LinearLayout>

这里需要先添加一个array.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string-array name="recycler_list">
        <item>Recycler0</item>
        <item>Recycler1</item>
        <item>Recycler2</item>
    </string-array>

</resources>

最后是activity的代码:

public class RecyclerActivity extends Activity {
    private RecyclerView mRcList;
    private RecyclerAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    private Spinner mSpinner;

    private List<String> mData = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler);
        mRcList = (RecyclerView) findViewById(R.id.rc_list);
        mLayoutManager = new LinearLayoutManager(this);
        mRcList.setLayoutManager(mLayoutManager);
        mRcList.setHasFixedSize(true);
        // 设置显示动画
        mRcList.setItemAnimator(new DefaultItemAnimator());

        mSpinner = (Spinner) findViewById(R.id.spinner);
        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                    int position, long id) {
                if (position == 0) {
                    mRcList.setLayoutManager(
                    // 设置为线性布局
                    new LinearLayoutManager(RecyclerActivity.this));
                } else if (position == 1) {
                    mRcList.setLayoutManager(
                    // 设置为表格布局
                    new GridLayoutManager(RecyclerActivity.this, 3));
                } else if (position == 2) {
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        // 增加测试数据
        mData.add("Recycler");
        mData.add("Recycler");
        mData.add("Recycler");
        mAdapter = new RecyclerAdapter(mData);
        mRcList.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(final View view, int position) {
                // 设置点击动画
                view.animate().translationZ(15F).setDuration(300)
                        .setListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                super.onAnimationEnd(animation);
                                view.animate().translationZ(1f)
                                        .setDuration(500).start();
                            }
                        }).start();
            }
        });
    }

    public void addRecycler(View view) {
        mData.add("Recycler");
        int position = mData.size();
        if (position > 0) {
            mAdapter.notifyDataSetChanged();
        }
    }

    public void delRecycler(View view) {
        int position = mData.size();
        if (position > 0) {
            mData.remove(position - 1);
            mAdapter.notifyDataSetChanged();
        }
    }

}

运行结果:
这里写图片描述


6.2、CardView

在Android 5.X之后,Google就提供了CardView的控件。其实CardView也是一个容器类布局,只是它提供了卡片这样一种形式。开发者可以定义卡片的大小与视图高度,并设置圆角的角度。
需要在项目中引入依赖:

compile 'com.android.support:cardview-v7:25.+'

主要是设置两个属性:第一个是设置背景颜色;第二个是设置圆角的角度:

    app:cardBackgroundColor="#1664a9"
    app:cardCornerRadius="10dp"

演示代码:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:layout_margin="10dp"
    app:cardBackgroundColor="#1664a9"
    app:cardCornerRadius="10dp"
    app:cardElevation="10dp"
    app:contentPadding="16dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="50dp"
            android:layout_weight="1"
            android:orientation="vertical"
            android:padding="8dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="中国工商银行"
                android:textColor="#ffffff"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="银联卡"
                android:textColor="#ffffff"
                android:textSize="16sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center_vertical"
                android:text="**** **** **** 8888"
                android:textColor="#ffffff"
                android:textSize="22sp" />
        </LinearLayout>

    </LinearLayout>
</android.support.v7.widget.CardView>

运行结果:
这里写图片描述




7、Activity过渡动画

曾经的Android在Activity进行跳转的时候,即使使用overridePendingtransition(int inId,int outId)这个方法,动画效果也是差强人意的。

但是Android 5.X 提供了三种Transition类型:

  • 进入:一个进入的过渡动画决定Activity中的所有的视图怎么进入屏幕。
  • 退出:一个退出的过渡动画决定一个Activity中的所有视图怎么退出屏幕。
  • 共享元素:一个共享元素过渡动画决定两个Activity之间的过渡,怎么共享它们的视图。

其中,进入和退出效果包括:

  • explode(分解):从屏幕中间进或出,移动视图
  • slide(滑动):从屏幕边缘进或出,移动视图
  • fade(淡出):通过改变屏幕上视图的不透明度达到添加或者移除视图

共享元素包括:

  • changeBounds:改变目标视图的布局边界
  • changeClipBounds:裁剪目标视图边界
  • changeTransform:改变目标视图的缩放比例和旋转角度
  • changeImageTransform:改变目标图片的大小和缩放比例



过度动画
要使用三种Activity过度动画非常简单,例如从ActivityA跳转到ActivityB,只需在ActivityA中将基本的startActivity(intent)方法改为:

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

而在ActivityB中,设置情况如下:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

或者在样式文件中设置如下代码:

<item name="android:windowContentTransitions">true</item>

那么接下来就可以设置进入ActivityB的具体的动画效果了:

getWindow().setEnterTransition(new Explode());
getWindow().setEnterTransition(new Slide());
getWindow().setEnterTransition(new Fade());

或者通过如下代码来设置离开ActivityB的动画效果:

getWindow().setExitTransition(new Explode());
getWindow().setExitTransition(new Slide());
getWindow().setExitTransition(new Fade());



共享元素
共享元素的使用,首先要在ActivityA的布局文件中设置共享的元素:

android:transitionName="XXX"

同时在ActivityB的布局文件中,给要实现共享效果的元素也增加相同的属性,需要注意的是一定要保证命名相同:

android:transitionName="XXX"

如果只有一个共享元素,那么在ActivityA中只需使用如下代码。使用的参数就是在前面普通动画的基础上增加了共享的View和前面取的名字:

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this,view,"share").toBundle());

如果有多个共享元素,那么可以通过Pair.create()来创建多个共享元素,代码如下:

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, 
        Pair.create(view,"share"),Pair.create(fab,"fab")).toBundle());

下面通过一个实例来演示Activity的过渡动画,ActivityA的代码如下:

public class TransitionActivity extends Activity {
     private Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
    }
        // 设置不同动画效果
        public void explode(View view) {
            intent = new Intent(this, TransitionsActivity.class);
            intent.putExtra("flag", 0);
            startActivity(intent,
                    ActivityOptions.makeSceneTransitionAnimation(this)
                            .toBundle());
        }
        // 设置不同动画效果
        public void slide(View view) {
            intent = new Intent(this, TransitionsActivity.class);
            intent.putExtra("flag", 1);
            startActivity(intent,
                    ActivityOptions.makeSceneTransitionAnimation(this)
                            .toBundle());
        }
        // 设置不同动画效果
        public void fade(View view) {
            intent = new Intent(this, TransitionsActivity.class);
            intent.putExtra("flag", 2);
            startActivity(intent,
                    ActivityOptions.makeSceneTransitionAnimation(this)
                            .toBundle());
        }
        // 设置不同动画效果
        public void share(View view) {
            View fab = findViewById(R.id.fab_button);
            intent = new Intent(this, TransitionsActivity.class);
            intent.putExtra("flag", 3);
            // 创建单个共享元素
//          startActivity(intent,
//                  ActivityOptions.makeSceneTransitionAnimation(
//                          this, view, "share").toBundle());
            startActivity(intent,
                    ActivityOptions.makeSceneTransitionAnimation(
                            this,
                            // 创建多个共享元素
                            Pair.create(view, "share"),
                            Pair.create(fab, "fab")).toBundle());
        }

}

相对应的布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.transition.TransitionActivity" >

    <Button
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:onClick="explode"
        android:text="explode" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:onClick="slide"
        android:text="slide" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:onClick="fade"
        android:text="fade" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:onClick="share"
        android:text="share"
        android:transitionName="share" />

    <Button
        android:id="@+id/fab_button"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:background="@drawable/ripple_round"
        android:elevation="5dp"
        android:transitionName="fab" />

</LinearLayout>

ActivityB代码如下:

public class TransitionsActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        int flag = getIntent().getExtras().getInt("flag");
        // 设置不同的动画效果
        switch (flag) {
        case 0:
            getWindow().setEnterTransition(new Explode());
            break;
        case 1:
            getWindow().setEnterTransition(new Slide());
            break;
        case 2:
            getWindow().setEnterTransition(new Fade());
            getWindow().setExitTransition(new Fade());
            break;
        case 3:
            break;
        }
        setContentView(R.layout.activity_transitions);
    }
}

相对应的布局代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.itman.androidfive.transition.TransitionsActivity" >

    <View
        android:id="@+id/holder_view"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="#2A8AF1"
        android:transitionName="share" />

    <Button
        android:id="@+id/fab_button"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:layout_alignParentEnd="true"
        android:layout_below="@+id/holder_view"
        android:layout_marginRight="@dimen/activity_horizontal_margin"
        android:layout_marginTop="-26dp"
        android:background="@drawable/ripple_round"
        android:elevation="5dp"
        android:transitionName="fab" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/holder_view"
        android:paddingTop="10dp" >

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_below="@+id/button4"
            android:layout_marginTop="10dp" />

        <Button
            android:id="@+id/button4"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_alignParentStart="true"
            android:layout_marginTop="10dp" />
    </RelativeLayout>

</RelativeLayout>

过度动画的运行结果:
这里写图片描述




8、Material Design动画效果

Android 5.X的UI设计Material Design中使用了大量的动画效果,同时Google也在官方设计文档上增加了对动画的设计指导。

8.1、Ripple效果

Ripple效果其实就是点击后的波纹效果。可以通过下面的代码来设置波纹的背景:

//波纹有边界
android:background="?android:attr/selectableItemBackground"
//波纹无边界
android:background="?android:attr/selectableItemBackgroundBorderless"

下面通过一个实例来演示这两种效果:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_light"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.materialdesign.RippleActivity" >

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="?android:attr/selectableItemBackground"
        android:text="有界波纹"
        android:textColor="@android:color/white" />

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="?android:attr/selectableItemBackgroundBorderless"
        android:text="无界波纹"
        android:textColor="@android:color/white" />

</LinearLayout>

运行效果:

这里写图片描述


同样的也可以在XML中直接来创建一个具有Ripple效果的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorPrimary" >

    <item>
        <shape android:shape="oval" >
            <solid android:color="#5EA5F5" />
        </shape>
    </item>

</ripple>

使用方法:

    <Button
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/ripple_round" />

运行结果:
这里写图片描述


8.2、Circular Reveal

这个动画具体效果表现为一个View一圆形的形式展开、揭示出来。通过ViewAnimationUtils.createCircularReveal()方法可以创建一个RevealAnimator动画。代码如下:

public static Animator createCircularReveal(View view, int centerX, 
int centerY, float startRadius, float endRadius) {
     return new RevealAnimator(view,centerX,centerY,startRadius,endRadius);
}

RevealAnimator的使用非常简单,主要是设置几个关键的坐标点:

  • centerX:动画开始的中心点X
  • centerY:动画开始的中心点Y
  • startRadius:动画开始半径
  • startRadius:动画结束半径

通过下面的例子,可以非常直观地感受到这种动画效果,xml代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.materialdesign.CircularRevealActivity" >

    <ImageView
        android:id="@+id/oval"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/oval" />

    <ImageView
        android:id="@+id/rect"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@drawable/rect" />

</LinearLayout>

这里的圆的xml补上:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight" >

    <item>
        <shape android:shape="oval" >
            <solid android:color="#738ffe" />
        </shape>
    </item>

</ripple>

方形的xml:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight" >

    <item>
        <shape android:shape="rectangle" >
            <solid android:color="#738ffe" />
        </shape>
    </item>

</ripple>

程序代码如下:

public class CircularRevealActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circular_reveal);

        final View oval = findViewById(R.id.oval);
        oval.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Animator animator = ViewAnimationUtils.createCircularReveal(
                        oval, oval.getWidth() / 2, oval.getHeight() / 2,
                        oval.getWidth(), 0);
                animator.setInterpolator(new AccelerateDecelerateInterpolator());
                animator.setDuration(1000);
                animator.start();
            }
        });
        final View rect = findViewById(R.id.rect);
        rect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Animator animator = ViewAnimationUtils.createCircularReveal(
                        rect, 0, 0, 0,
                        (float) Math.hypot(rect.getWidth(), rect.getHeight()));
                animator.setInterpolator(new AccelerateInterpolator());
                animator.setDuration(1000);
                animator.start();
            }
        });
    }

}

运行结果:

这里写图片描述


8.3、View state changes Animation

在Android 5.X中,系统提供了视图状态改变来设置一个视图的状态切换动画。

  • StateListAnimator

StateListAnimator作为视图改变时的动画效果,通常会使用Selector来进行设置,但以前设置Selector的时候,通常是修改背景来达到反馈的效果。现在可以使用动画来作为视图改变的效果。

在XML中定义一个StateListAnimator,并添加到Selector中:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:property="rotationX" 
        android:duration="@android:integer/config_shortAnimTime" 
        android:valueTo="360" 
        android:valuyeType="floatType" />
        </set>
    </item>
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:property="rotationX"
        android:duration="@android:integer/config_shortAnimTime" 
        android:valueTo="0" 
        android:valuyeType="floatType" />
        </set>
    </item>
</selector>

在布局中直接即可使用:

<Button
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="@drawable/anim_change" />

同样,在代码中也可以调用AnimatorInflater.loadStateListAnimator()方法,并且通过View.setStateListAnimator()方法分配动画到视图上。

  • animated-selector

animated-selector同样是一个状态改变的动画效果Selelctor。
先准备一套状态变换图:
这里写图片描述

接着在xml中定义这些图片的不同状态:

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/state_on"
        android:state_checked="true">
        <bitmap android:src="@drawable/ic_done_anim_030" />
    </item>
    <item android:id="@+id/state_off">
        <bitmap android:src="@drawable/ic_plus_anim_030" />
    </item>
    <transition
        android:fromId="@+id/state_on"
        android:toId="@+id/state_off">
        <animation-list>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_000" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_001" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_002" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_003" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_004" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_005" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_006" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_007" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_008" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_009" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_010" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_011" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_012" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_013" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_014" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_015" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_016" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_017" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_018" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_019" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_020" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_021" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_022" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_023" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_024" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_025" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_026" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_027" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_028" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_029" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_plus_anim_030" />
            </item>
        </animation-list>
    </transition>
    <transition
        android:fromId="@+id/state_off"
        android:toId="@+id/state_on">
        <animation-list>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_000" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_001" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_002" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_003" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_004" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_005" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_006" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_007" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_008" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_009" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_010" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_011" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_012" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_013" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_014" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_015" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_016" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_017" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_018" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_019" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_020" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_021" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_022" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_023" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_024" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_025" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_026" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_027" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_028" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_029" />
            </item>
            <item android:duration="16">
                <bitmap android:src="@drawable/ic_done_anim_030" />
            </item>
        </animation-list>
    </transition>
</animated-selector>

最后再程序代码中通过setImageState()方法来改变一个背景状态图:

public class AnimatedSelectorActivity extends Activity {
    private boolean mIsCheck;
    private static final int[] STATE_CHECKED = new int[] { android.R.attr.state_checked };
    private static final int[] STATE_UNCHECKED = new int[] {};
    private ImageView mImageView;
    private Drawable mDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animated_selector);
        mImageView = (ImageView) findViewById(R.id.image);
        mDrawable = getResources().getDrawable(R.drawable.fab_anim);
        mImageView.setImageDrawable(mDrawable);
    }

    public void anim(View view) {
        if (mIsCheck) {
            mImageView.setImageState(STATE_UNCHECKED, true);
            mIsCheck = false;
        } else {
            mImageView.setImageState(STATE_CHECKED, true);
            mIsCheck = true;
        }
    }

}

运行结果:
这里写图片描述




9、Toolbar

Toolbar与Actionbar最大的区别就是Toolbar更加自由、可控。要使用Toolbar必须引入appcompat-v7支持,并设置主题为NoActionBar,因此在styles.xml文件中,使用如下代码:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- toolbar颜色-->
        <item name="colorPrimary">@color/colorPrimary</item>
        <!-- 状态栏颜色-->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <!-- 窗口的背景颜色-->
        <item name="android:windowBackground">@android:color/white</item>
        <!-- add SearchView-->
        <item name="android:searchViewStyle">@style/MySearchView</item>
    </style>
    <style name="MySearchView" parent="Widget.AppCompat.SearchView" />
</resources>

用案例实现添加Toolbar显示的标题和图标,再布局中声明Toolbar:

<android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize" />

在Menu文件夹中创建一个Menu的XML文件:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity" >

    <item
        android:id="@+id/ab_search"
        android:orderInCategory="80"
        android:title="action_search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/action_share"
        android:orderInCategory="90"
        android:title="action_share"
        app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="action_settings"
        app:showAsAction="never"/>

</menu>

activity代码中实现:

public class ToolbarActivity extends AppCompatActivity {
    private ShareActionProvider mShareActionProvider;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setLogo(R.drawable.ic_launcher);
        toolbar.setTitle("主标题");
        toolbar.setSubtitle("副标题");
        setSupportActionBar(toolbar);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }
}

运行效果:

这里写图片描述


接下来修改一下布局,实现Toolbar的侧滑菜单:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.itman.androidfive.toolbar.ToolbarActivity" >

 <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- 内容界面 -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/holo_blue_light"
            android:orientation="vertical">

            <Button
                android:layout_width="100dp"
                android:layout_height="match_parent"
                android:text="内容界面" />
        </LinearLayout>

        <!-- 侧滑菜单内容 必须指定其水平重力 -->
        <LinearLayout
            android:id="@+id/drawer_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:orientation="vertical">

            <Button
                android:layout_width="200dp"
                android:layout_height="match_parent"
                android:text="菜单界面" />
        </LinearLayout>
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

在activity代码中的实现:

public class ToolbarActivity extends ActionBarActivity {
    private Toolbar mToolbar;
    private ShareActionProvider mShareActionProvider;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar);
        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mToolbar.setLogo(R.drawable.ic_launcher);
        // 标题的文字需在setSupportActionBar之前,不然会无效
        mToolbar.setTitle("主标题");
        mToolbar.setSubtitle("副标题");
        setSupportActionBar(mToolbar);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                mToolbar, R.string.abc_action_bar_home_description,
                R.string.abc_action_bar_home_description_format);
        mDrawerToggle.syncState();
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // 菜单的监听可以在toolbar里设置,
        // 也可通过Activity的onOptionsItemSelected回调方法来处理
        mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                case R.id.action_settings:
                    Toast.makeText(ToolbarActivity.this, "action_settings",
                            Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
                }
                return true;
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        /* ShareActionProvider配置 */
        mShareActionProvider = (ShareActionProvider) MenuItemCompat
                .getActionProvider(menu.findItem(R.id.action_share));
        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/*");
        mShareActionProvider.setShareIntent(intent);
        return super.onCreateOptionsMenu(menu);
    }

}

运行结果:
这里写图片描述




10、Notification

google在Android5.0 上又进一步改进了通知栏,优化了Notification。当我们长按Notification的时候,会显示消息来源;同时,在Android 5.X 设备上,锁屏状态下我们也可以看见Notification的通知。

10.1、基本的Notification

直接演示案例:

public class NotificationOneActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification_one);
        // 第一步:初始化
        Notification.Builder builder = new Notification.Builder(this);
        // 第二步:构建点击之后的意图
        Intent intent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("http://www.baidu.com"));
        // 构造pendingdintent
        PendingIntent pendingIntent = PendingIntent.getActivities(this, 0,
                new Intent[] { intent }, 0);
        // 第三步:设置通知栏的各种消息
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentIntent(pendingIntent);
        builder.setAutoCancel(true);
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_launcher));
        builder.setContentText("Title");
        builder.setContentText("内容");
        builder.setSubText("text");
        // 第四步:通过NotificationManager来发出
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(0, builder.build());
    }

}

运行结果:
这里写图片描述


10.2、折叠式Notification

案例演示,先准备两个布局,notification.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textColor="#ff43aebe" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/robot" />

</LinearLayout>

notification_expanded.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="right|top"
    android:orientation="horizontal" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="false"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:layout_toLeftOf="@+id/imageView"
            android:gravity="center"
            android:text="I am now expanded"
            android:textColor="#ff43aebe" />

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_gravity="right|top"
            android:src="@drawable/robot_expanded" />
    </RelativeLayout>

</LinearLayout>

activity代码:

public class NotificationTwoActivity extends Activity {
    private static final int NOTIFICATION_ID_COLLAPSE = 0x01;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification_two);
        Intent intent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("http://www.sina.com"));
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                intent, 0);
        Notification.Builder builder = new Notification.Builder(this);
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentIntent(pendingIntent);
        builder.setAutoCancel(true);
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_launcher));
        // 通过RemoteViews来创建自定义的Notification视图
        RemoteViews contentView = new RemoteViews(getPackageName(),
                R.layout.notification);
        contentView.setTextViewText(R.id.textView, "show me when collapsed");
        Notification notification = builder.build();
        notification.contentView = contentView;
        // 通过RemoteViews来创建自定义的Notification视图
        RemoteViews expandedView = new RemoteViews(getPackageName(),
                R.layout.notification_expanded);
        notification.bigContentView = expandedView;
        NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        nm.notify(NOTIFICATION_ID_COLLAPSE, notification);
    }

}

运行结果,模拟器有点菜,没有显示出折叠的样式:
这里写图片描述

10.3、悬挂式Notification

案例演示:

public class NotificationThreeActivity extends Activity {
    private static final int NOTIFICATION_ID_HEADSUP = 0x01;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification_three);

        Notification.Builder builder = new Notification.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setPriority(Notification.PRIORITY_DEFAULT)
                .setCategory(Notification.CATEGORY_MESSAGE)
                .setContentTitle("Headsup Notification")
                .setContentText("I am a Headsup notification.");
        Intent push = new Intent();
        push.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        push.setClass(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, push,
                PendingIntent.FLAG_CANCEL_CURRENT);
        builder.setContentText("Heads-Up Notification on Android 5.0")
                .setFullScreenIntent(pendingIntent, true);
        NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        nm.notify(NOTIFICATION_ID_HEADSUP, builder.build());
    }

}

运行结果:
这里写图片描述

10.4、显示等级的Notification

在Android 5.X 将Notification分成三个等级:

  • VISIBILITY_PRIVATE:表明只有当没有锁屏的时候会显示
  • VISIBILITY_PUBLIC:表明在任何情况下都会显示
  • VISIBILITY_SECRET:表明在pin、password等安全锁和没有锁屏的情况下才能够显示

设置Notification等级的方式非常简单,同样是借助builder对象:

builder.setVisibility(Notification.VISIBILITY_PUBLIC);

Notification在Android 5.X中的改动非常多,增加了设置Notification背景颜色的接口:

builder.setColor(Color.RED);

增加了设置Notification的category接口,category用来确定Notification显示的位置,参数就是各种category的类型:

builder.setCategory(Notification.CATEGORY_MESSAGE);

源码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值