2014年,Google携Android5.X重装归来,全新的UI设计和更加优化的性能,令开发者眼前一亮
开发Android还得靠AS,下载地址
http://developer.android.com/intl/zh-cn/sdk/index.html
Google通过模拟自然界纸墨的形态变化、光线与阴影、纸与纸之间的控件层级关系,带来一种真实的空间感
Android5.x大量加入了各种新的动画效果,让整个设计风格更加自然和谐。
Material Desigin中运用了大量高度饱和、适中亮度的大色块来突出界面的主次,并一扫Android4.X系列Holo主题的沉重感,让界面更加富有时尚感和视觉冲击力
此外还有很多新的设计风格,如悬浮按钮,聚焦大图、无框按钮、波纹效果等新特性
具体可参考
http://www.google.com/design/#resources
之前的ARM模拟器,是以软件的形式模拟,所以很慢~x86可以选这使用宿主机器的GPU等,和真机的速度相差无几~
install 之后
找到SDK如下目录,因为这个加速器是跨平台的,windows操作系统对应的是exe执行文件,安装即可
当然你也可以使用genymotion~有真机最好了~
除了从SDK中下载,还可以从Intel官方网站上下载加速器
官网如下:
https://software.intel.com/zh-cn/android
https://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-manager/
cmd命令行窗口:
虽然我们上面安装了加速器,但是只是模拟器而已,镜像才是关键!!!
官方推荐的安装方法
因为我的电脑操作系统是64位,我们打算在5.0的模拟器中使用,所以选择如下:
https://software.intel.com/zh-cn/android/articles/android-44-kitkat-x86-emulator-system-image
指导文档
下载后放到相应的目录即可~
哈哈 速度那是必须的快~
Material Design现在有三种默认的主题可以设置:
同时 Android5.x提出了Color Palette (颜色调色板)的概念,让开发者可以自己设定系统区域的颜色,使整个APP的颜色风格和系统的颜色风格保持一致。
通过如下代码,可以通过使用自定义Style的方式来创建自己的Color Palette 颜色主题,从而实现不同的颜色风格。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="android:Theme.Material"> <!--appBar的颜色--> <item name="android:colorPrimary">#BEBEBE</item> <!--状态栏的颜色--> <item name="android:colorPrimaryDark">#FF5AEBFF</item> <item name="android:navigationBarColor">#FFFF4130</item> <item name="android:colorAccent">#BF3EFF</item> </style>
</resources>
Android Studio开发工具,在本项目的build.gradle文件中添加
compile 'com.android.support:recyclerview-v7:23.1.1'
如果是eclipse的话,下载jar包,放到lib下,一般都会自动的build path,检查下即可。
如何下载jar ?
在SDK Manager中下载Support Library
sdk\extras\android\support\v7\recyclerview\libs
package demo.turing.com.materialdesignwidget.recyclerView;
import java.util.ArrayList;
import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
/** * MyApp * * @author Mr.Yang on 2016-03-30 20:21. * @version 1.0 * @desc */
public class SimulatorData {
public static ArrayList<SampleModel> getSampleModelData(int size) {
ArrayList<SampleModel> sampleData = new ArrayList<SampleModel>(size);
for (int i = 0; i < size; i++) {
sampleData.add(new SampleModel("新的列表项< " + i + " >"));
}
return sampleData;
}
}
package demo.turing.com.materialdesignwidget.recyclerView.model;
/** * MyApp * * @author Mr.Yang on 2016-03-30 20:23. * @version 1.0 * 对应Item中药显示的数据项 */
public class SampleModel {
private String text;
public SampleModel(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
package demo.turing.com.materialdesignwidget.recyclerView;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/** * MyApp * * @author Mr.Yang on 2016-03-30 20:37. * @version 1.0 * 分隔条 */
public class SampleDivider extends RecyclerView.ItemDecoration {
// 默认分隔条Drawable资源的ID,使用系统自带的
private static final int[] ATTRS = {android.R.attr.listDivider};
// 分隔条Drawable对象
private Drawable mDivider;
/** * 构造函数 * @param context */
public SampleDivider(Context context) {
// 使用TypedArray装载定义的ATTRS
TypedArray a = context.obtainStyledAttributes(ATTRS);
// 获取系统提供的分隔条Drawable对象
mDivider = a.getDrawable(0);
// 回收TypedArray所占用的空间
a.recycle();
}
/** * 在该方法中绘制了所有列表项之间的分隔条, * 将分隔条看做是一个非常非常窄的矩形,每个Item的左右是一样的,只是上下不同, * 在for循环中计算top和bottom */
@Override
public void onDrawOver(Canvas c, RecyclerView parent) {
// 获取列表项距离左边缘的距离
int left = parent.getPaddingLeft();
// 获取列表项距离右边缘的距离
int right = parent.getWidth() - parent.getPaddingRight();
// 获取列表项的总数
int childCount = parent.getChildCount();
// 开始绘制所有列表项之间的分隔线
for (int i = 0; i < childCount; i++) {
// 获得当前的列表项
View child = parent.getChildAt(i);
// 获取当前列表项的布局参数信息
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
// 计算分隔条左上角的纵坐标
int top = child.getBottom() + params.bottomMargin;
// 计算分隔条右下角的纵坐标
int bottom = top + mDivider.getIntrinsicHeight();
// 设置分隔条绘制的位置
mDivider.setBounds(left, top, right, bottom);
// 开始绘制当前列表项下方的分隔条
mDivider.draw(c);
}
}
}
package demo.turing.com.materialdesignwidget.recyclerView.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Random;
import demo.turing.com.materialdesignwidget.R;
import demo.turing.com.materialdesignwidget.recyclerView.SimulatorData;
import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
/** * MyApp * * @author Mr.Yang on 2016-03-30 21:03. * @version 1.0 * @desc */
public class SampleRecyclerAdapter extends RecyclerView.Adapter<SampleRecyclerAdapter.ViewHolder> {
// 模拟数据
private final ArrayList<SampleModel> sampleData = SimulatorData.getSampleModelData(20);
/** * 用于创建控件 * * @param parent * @param viewType * @return */
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 获得列表项控件(LinearLayer对象)
// list_basic_item.xml布局文件中只包含一个<LinearLayer>标签,
// 在该标签中包含了一个<TextView>标签, item是LinearLayout对象
View item = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_basic_item, parent, false);
return new ViewHolder(item);
}
/** * 为控件设置数据 * * @param holder * @param position */
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// 获取当前item中显示的数据
final SampleModel rowData = sampleData.get(position);
// 设置要显示的数据
holder.textViewSample.setText(rowData.getText());
// 设置tag
holder.itemView.setTag(rowData);
}
@Override
public int getItemCount() {
return sampleData.size();
}
/** * 删除指定的Item * @param position */
public void removeData(int position) {
sampleData.remove(position);
// 通知RecyclerView控件某个Item已经被删除
notifyItemRemoved(position);
}
/** * 在指定位置添加一个新的Item * @param positionToAdd */
public void addItem(int positionToAdd) {
sampleData.add(positionToAdd, new SampleModel("新的列表项" + new Random().nextInt(10000)));
// 通知RecyclerView控件插入了某个Item
notifyItemInserted(positionToAdd);
}
/** * 对应Item中的控件 */
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textViewSample;
public ViewHolder(View itemView) {
super(itemView);
textViewSample = (TextView) itemView
.findViewById(R.id.textViewSample);
}
}
}
package demo.turing.com.materialdesignwidget.recyclerView;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import demo.turing.com.materialdesignwidget.R;
import demo.turing.com.materialdesignwidget.recyclerView.adapter.SampleRecyclerAdapter;
public class RecyclerViewAct extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view);
// 获取RecyclerView对象
final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
// 创建线性布局管理器(默认是垂直方向)
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 为RecyclerView指定布局管理对象
recyclerView.setLayoutManager(layoutManager);
// 创建列表项分隔线对象
final RecyclerView.ItemDecoration itemDecoration = new SampleDivider(this);
// 为RecyclerView控件指定分隔线对象
recyclerView.addItemDecoration(itemDecoration);
final SampleRecyclerAdapter sampleRecyclerAdapter = new SampleRecyclerAdapter();
recyclerView.setAdapter(sampleRecyclerAdapter);
}
}
package demo.turing.com.materialdesignwidget.cardView;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.widget.SeekBar;
import android.widget.Toast;
import demo.turing.com.materialdesignwidget.R;
public class CardViewAct extends AppCompatActivity {
private CardView mCardView;
private SeekBar mRadiusSeekBar,mElevationSeekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_view);
mCardView = (CardView)findViewById(R.id.cardview);
mRadiusSeekBar = (SeekBar)findViewById(R.id.cardview_radius_seekbar);
mRadiusSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar)
{
// TODO Auto-generated method stub
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser)
{
mCardView.setRadius(progress);
}
});
mElevationSeekBar = (SeekBar)findViewById(R.id.cardview_elevation_seekbar);
mElevationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
/** * 加了 @TargetApi(Build.VERSION_CODES.LOLLIPOP) * 在API21上运行时没有问题的,但是低版本的会报错,最好做下判断 * @param seekBar * @param progress * @param fromUser */
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mCardView.setElevation(progress);
} else{
Toast.makeText(CardViewAct.this,"5.0以下版本不支持~",Toast.LENGTH_SHORT).show();
}
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin">
<android.support.v7.widget.CardView android:id="@+id/cardview" android:layout_width="fill_parent" android:layout_height="160dp" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large" android:elevation="100dp" card_view:cardBackgroundColor="@color/cardview_initial_background" card_view:cardCornerRadius="8dp" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="@dimen/margin_medium" android:text="@string/cardview_contents" />
</android.support.v7.widget.CardView>
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_large" android:orientation="horizontal">
<TextView android:layout_width="@dimen/seekbar_label_length" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/cardview_radius_seekbar_text" />
<SeekBar android:id="@+id/cardview_radius_seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/margin_medium" />
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:layout_width="@dimen/seekbar_label_length" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/cardview_elevation_seekbar_text" />
<SeekBar android:id="@+id/cardview_elevation_seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/margin_medium" />
</LinearLayout>
</LinearLayout>
</ScrollView>
Material Design的一个很重要的特性就是拟物扁平化。
以往的Android View通常有2个属性——X和Y,而在Android5.X中,Google为其增加了一个新的属性 —Z,对应垂直方向上的高度变化。
在Android5.x中,View的Z值由 elevation + translationZ(这两个都是5.x引入的新特性)组成。
其中 elevation是静态的成员,translationZ可以在代码中使用来实现动画的效果。
Z = elevation + translationZ
在xml中设置View的视图高度
android:elevation="Xxdp"
比如:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/cardview_contents" android:elevation="10dp" />
view.setTranslationZ(XXX)
通常也会使用属性动画来为视图高度改变的时候增加一个动画效果
if(flag){
view.animate().translationZ(100);
flag=false;
}else{
view.animate().translationZ(0);
flag=true;
}