实现Instagram的Material Design概念设计

几个月前(这篇文章的日期是2014 年11月10日),google发布了app和web应用的Material Design设计准则之后,设计师Emmanuel Pacamalan在youtube上发布了一则概念视频,演示了Instagram如果做成Material风格会是什么样子:

视频地址 http://v.youku.com/v_show/id_XODg2NDQ1NDQ4.html

这仅仅是停留在图像上的设计,是美好的愿景,估计很多人都会问,能否使用相对简单的办法将它实现出来呢?答案是:yes,不仅仅能实现,而且无须要求在Lillipop版本,实际上几年前4.0发布之后我们就可以实现这些效果了。ps 读到这里我们应该反思这几年开发者是不是都吃屎去了。

鉴于这个原因,我决定开始撰写一个新的课题-如何将INSTAGRAM with Material Design 视频中的效果转变成现实。当然,我们并不是真的要做一个Instagram应用,只是将界面做出来而已,并且尽量减少一些不必要的细节。

开始

本文将要实现的是视频中前7秒钟的效果。我觉得对于第一次尝试来说已经足够了。我想要提醒诸位的是,里面的实现方法不仅仅是能实现,也是我个人最喜欢的实现方式。还有,我不是一个美工,因此项目中的所有图片是直接从网上公开的渠道获取的。(主要是从resources page)。

好了,下面是最终效果的两组截图和视频(很短的视频,就是那7秒钟的效果,可以在上面的视频中看到,这里因为没法直接引用youtube的视频就略了)(分别从Android 4 和5上获得的):

准备

在我们的项目中,将使用一些热门的android开发工具和库。并不是所有这些东西本篇文章都会用到,我只是将它们准备好以备不时之需。

初始化项目

首先我们需要创建一个新的android项目。我使用的是Android Studio和gradle的build方式。最低版本的sdk是15(即Android 4.0.4)。然后我们将添加一些依赖。没什么好讲的,下面是build.gradle以及app/build.gradle文件的代码:

build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath ‘com.android.tools.build:gradle:0.14.0‘
        classpath ‘com.jakewharton.hugo:hugo-plugin:1.1.+‘
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

app/build.gradle

apply plugin: ‘com.android.application‘
apply plugin: ‘hugo‘

android {
    compileSdkVersion 21
    buildToolsVersion "21.1"

    defaultConfig {
        applicationId "io.github.froger.instamaterial"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])

    compile "com.android.support:appcompat-v7:21.0.0"
    compile ‘com.android.support:support-v13:21.+‘
    compile ‘com.android.support:support-v4:21.+‘
    compile ‘com.android.support:palette-v7:+‘
    compile ‘com.android.support:recyclerview-v7:+‘
    compile ‘com.android.support:cardview-v7:21.0.+‘
    compile ‘com.jakewharton:butterknife:5.1.2‘
    compile ‘com.jakewharton.timber:timber:2.5.0‘
    compile ‘com.facebook.rebound:rebound:0.3.6‘
}

简而言之,我们有如下工具:

一些兼容包(CardView, RecyclerView, Palette, AppCompat)-我喜欢使用最新的控件。当然你完全可以使用ListView Actionbar甚至View/FrameView来替代,但是为什么要这么折腾?

ButterKnife - view注入工具简化我们的代码。(比方说不再需要写findViewById()来引用view,以及一些更强大的功能)。

Rebound - 我们目前还没有用到,但是我以后肯定会用它。这个facebook开发的动画库可以让你的动画效果看起来更自然。

Timber
Hugo - 对这个项目而言并不是必须,我仅仅是用他们打印log。

图片资源

本项目中将使用到一些Material Design的图标资源。App 图标来自于NSTAGRAM with Material Design 视频,这里complete
bunch of images
是项目的全套资源。

样式

我们从定义app的默认样式开始。同时为Android 4和5定义Material Desing样式的最简单的方式是直接继承Theme.AppCompat.NoActionBar 或者 Theme.AppCompat.Light.NoActionBar主题。为什么是NoActionBar?因为新的sdk中为我们提供了实现Actionbar功能的新模式。本例中我们将使用Toolbar控件,基于这个原因-Toolbar是ActionBar更好更灵活的解决方案。我们不会深入讲解这个问题,但你可以去阅读android开发者博客AppCompat
v21

根据概念视频中的效果,我们在AppTheme中定义了三个基本颜色(基色调):

styles.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- styles.xml-->
<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/style_color_primary</item>
        <item name="colorPrimaryDark">@color/style_color_primary_dark</item>
        <item name="colorAccent">@color/style_color_accent</item>
    </style>
</resources>

colors1.xml

<?xml version="1.0" encoding="utf-8"?>
<!--colors.xml-->
<resources>
    <color name="style_color_primary">#2d5d82</color>
    <color name="style_color_primary_dark">#21425d</color>
    <color name="style_color_accent">#01bcd5</color>
</resources>

关于这三个颜色的意义,你可以在这里找到Material Theme Color Palette documentation

布局

项目目前主要使用了3个主要的布局元素

  • Toolbar - 包含导航图标和applogo的顶部bar
  • RecyclerView - 用于显示feed
  • Floating Action Button - 一个实现了Material Design中action button pattern的ImageButton。

在开始实现布局之前,我们先在res/values/dimens.xml文件中定义一些默认值:

<?xml version="1.0" encoding="utf-8"?>
<!--dimens.xml-->
<resources>
    <dimen name="btn_fab_size">56dp</dimen>
    <dimen name="btn_fab_margins">16dp</dimen>
    <dimen name="default_elevation">8dp</dimen>
</resources>

这些值的大小是基于Material Design设计准则中的介绍。

现在我们来实现MainActivity中的layout:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

        <ImageView
            android:id="@+id/ivLogo"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:scaleType="center"
            android:src="@drawable/img_toolbar_logo" />
    </android.support.v7.widget.Toolbar>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvFeed"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar"
        android:scrollbars="none" />

    <ImageButton
        android:id="@+id/btnCreate"
        android:layout_width="@dimen/btn_fab_size"
        android:layout_height="@dimen/btn_fab_size"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="@dimen/btn_fab_margins"
        android:layout_marginRight="@dimen/btn_fab_margins"
        android:background="@drawable/btn_fab_default"
        android:elevation="@dimen/default_elevation"
        android:src="@drawable/ic_instagram_white"
        android:textSize="28sp" />

</RelativeLayout>

以上代码的解释:

  • 关于Toolbar最重要的特征是他现在是activity layout的一部分,而且继承自ViewGroup,因此我们可以在里面放一些UI元素(它们将利用剩余空间)。本例中,它被用来放置logo图片。同时,因为Toolbar是比Actionbar更灵活的控件,我们可以自定义更多的东西,比如设置背景颜色为colorPrimary(否则Toolbar将是透明的)。
  • RecyclerView虽然在xml中用起来非常简单,但是如果java代码中没有设置正确,app是不能启动的,会报java.lang.NullPointerException
  • Elevation(ImageButton中)属性不兼容api21以前的版本。所以如果我们想做到Floating Action Button的效果需要在Lollipop和Lollipop之前的设备上使用不同的background。

Floating Action Button

为了简化FAB的使用,我们将用对Lollipop以及Lollipop之前的设备使用不同的样式:

FAB for Android v21:

FAB for Android pre-21

我们需要创建两个不同的xml文件来设置button的background:/res/drawable-v21/btn_fab_default.xml(Lollipop设备) ,/res/drawable/btn_fab_default.xml(Lollipop之前的设备):

btn_fab_default2.xml

<?xml version="1.0" encoding="utf-8"?>
<!--drawable-v21/btn_fab_default.xml-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/fab_color_shadow">
    <item>
    <shape android:shape="oval">
    <solid android:color="@color/style_color_accent" />
    </shape>
    </item>
</ripple>

btn_fab_default1.xml

<?xml version="1.0" encoding="utf-8"?>
<!--drawable/btn_fab_default.xml-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <layer-list>
            <item android:bottom="0dp" android:left="2dp" android:right="2dp" android:top="2dp">
                <shape android:shape="oval">
                    <solid android:color="@color/fab_color_shadow" />
                </shape>
            </item>

            <item android:bottom="2dp" android:left="2dp" android:right="2dp" android:top="2dp">
                <shape android:shape="oval">
                    <solid android:color="@color/style_color_accent" />
                </shape>
            </item>
        </layer-list>
    </item>
    <item android:state_pressed="true">
        <shape android:bottom="2dp" android:left="2dp" android:right="2dp" android:shape="oval" android:top="2dp">
        <solid android:color="@color/fab_color_pressed" />
        </shape>
    </item>
</selector>

上面的代码涉及到两个颜色的定义,在res/values/colors.xml中添加:

<color name="btn_default_light_normal">#00000000</color>
<color name="btn_default_light_pressed">#40ffffff</color>

可以看到在 21之前的设备商制造阴影比较复杂。不幸的是在xml中达到真实的阴影效果没有渐变方法。其他的办法是使用图片的方式,或者通过java代码实现(参见creating fab shadow)。

Toolbar

现在我们来完成Toolbar。我们已经有了background和应用的logo,现在还剩下navigation以及menu菜单图标了。关于navigation,非常不幸的是,在xml中app:navigationIcon=""是不起作用的,而android:navigationIcon=""又只能在Lollipop上有用,所以只能使用代码的方式了:

toolbar.setNavigationIcon(R.drawable.ic_menu_white);

注:app:navigationIcon=""的意思是使用兼容包appcompat的属性,而android:navigationIcon=""是标准的sdk属性。

至于menu图标我们使用标准的定义方式就好了:

在res/menu/menu_main.xml中

<!--menu_main.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/action_inbox"
            android:icon="@drawable/ic_inbox_white"
            android:title="Inbox"
            app:showAsAction="always" />
</menu>

在activity中inflated这个menu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

本应运行的很好,但是正如我在twitter上提到的,Toolbar onClick  selectors有不协调的情况:

为了解决这个问题,需要做更多的工作,首先为menu item创建一个自定义的view

res/layout/menu_item_view.xml

<?xml version="1.0" encoding="utf-8"?>
<!--menu_item_view.xml-->
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="?attr/actionBarSize"
    android:layout_height="?attr/actionBarSize"
    android:background="@drawable/btn_default_light"
    android:src="@drawable/ic_inbox_white" />

然后为Lollipop和Lollipop之前的设备分别创建onClick的selector,在Lollipop上有ripple效果:

btn_default_light2.xml

<?xml version="1.0" encoding="utf-8"?>
<!--drawable-v21/btn_default_light.xml-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/btn_default_light_pressed" />

btn_default_light1.xml

<?xml version="1.0" encoding="utf-8"?>
<!--drawable/btn_default_light.xml-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/btn_default_light_normal" android:state_focused="false" android:state_pressed="false" />
    <item android:drawable="@color/btn_default_light_pressed" android:state_pressed="true" />
    <item android:drawable="@color/btn_default_light_pressed" android:state_focused="true" />
</selector>

现在,工程中的所有的color应该是这样子了:

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<!--colors.xml-->
<resources>
<color name="style_color_primary">#2d5d82</color>
<color name="style_color_primary_dark">#21425d</color>
<color name="style_color_accent">#01bcd5</color>

<color name="fab_color_pressed">#007787</color>
<color name="fab_color_shadow">#44000000</color>

<color name="btn_default_light_normal">#00000000</color>
<color name="btn_default_light_pressed">#40ffffff</color>
</resources>

最后我们应该将custom view放到menu item中,在onCreateOptionsMenu()中:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    inboxMenuItem = menu.findItem(R.id.action_inbox);
    inboxMenuItem.setActionView(R.layout.menu_item_view);
    return true;
}

以上就是toolbar的所有东西。并且onClick的按下效果也达到了预期的效果:

Feed

Last thing we should implement is feed, built on RecyclerView. Right now we have to setup two things: layout manager (RecyclerView has to know how to arrange items) and adapter (to provide items).

First thing is straightforward - while our layout is simple ListView we can useLinearLayoutManager for items arragement. For the second one we have to do more work, buth there is no magic to deal with.

Let’s start from defining list item layout (res/layout/item_feed.xml):

最后需要实现的是feed,基于RecyclerView实现。我们需要设置两个东西:layout manager和adapter,因为这里其实就是想实现ListView的效果,所以直接用LinearLayoutManager就行了,而adapter我们首先从item的布局开始(res/layout/item_feed.xml):

item_feed.xml

<?xml version="1.0" encoding="utf-8"?><!-- item_feed.xml -->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="8dp"
    card_view:cardCornerRadius="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_feed_top" />

        <io.github.froger.instamaterial.SquaredImageView
            android:id="@+id/ivFeedCenter"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <ImageView
            android:id="@+id/ivFeedBottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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

FeedAdapter也非常简单:

FeedAdapter.java

public class FeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int ANIMATED_ITEMS_COUNT = 2;

    private Context context;
    private int lastAnimatedPosition = -1;
    private int itemsCount = 0;

    public FeedAdapter(Context context) {
        this.context = context;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(context).inflate(R.layout.item_feed, parent, false);
        return new CellFeedViewHolder(view);
    }

    private void runEnterAnimation(View view, int position) {
        if (position >= ANIMATED_ITEMS_COUNT - 1) {
            return;
        }

        if (position > lastAnimatedPosition) {
            lastAnimatedPosition = position;
            view.setTranslationY(Utils.getScreenHeight(context));
            view.animate()
            .translationY(0)
            .setInterpolator(new DecelerateInterpolator(3.f))
            .setDuration(700)
            .start();
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
        runEnterAnimation(viewHolder.itemView, position);
        CellFeedViewHolder holder = (CellFeedViewHolder) viewHolder;
        if (position % 2 == 0) {
            holder.ivFeedCenter.setImageResource(R.drawable.img_feed_center_1);
            holder.ivFeedBottom.setImageResource(R.drawable.img_feed_bottom_1);
        } else {
            holder.ivFeedCenter.setImageResource(R.drawable.img_feed_center_2);
            holder.ivFeedBottom.setImageResource(R.drawable.img_feed_bottom_2);
        }
    }

    @Override
    public int getItemCount() {
        return itemsCount;
    }

    public static class CellFeedViewHolder extends RecyclerView.ViewHolder {
        @InjectView(R.id.ivFeedCenter)
        SquaredImageView ivFeedCenter;
        @InjectView(R.id.ivFeedBottom)
        ImageView ivFeedBottom;

        public CellFeedViewHolder(View view) {
        super(view);
            ButterKnife.inject(this, view);
        }
    }

    public void updateItems() {
        itemsCount = 10;
        notifyDataSetChanged();
    }
}

没什么特别之处需要说明。

通过以下方法将他们放在一起:

private void setupFeed() {
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    rvFeed.setLayoutManager(linearLayoutManager);
    feedAdapter = new FeedAdapter(this);
    rvFeed.setAdapter(feedAdapter);
}

下面是整个MainActivity class的源码:

//MainActivity.java
public class MainActivity extends ActionBarActivity {
    @InjectView(R.id.toolbar)
    Toolbar toolbar;
    @InjectView(R.id.rvFeed)
    RecyclerView rvFeed;

    private MenuItem inboxMenuItem;
    private FeedAdapter feedAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);

        setupToolbar();
        setupFeed();
    }

    private void setupToolbar() {
        setSupportActionBar(toolbar);
        toolbar.setNavigationIcon(R.drawable.ic_menu_white);
    }

    private void setupFeed() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        rvFeed.setLayoutManager(linearLayoutManager);
        feedAdapter = new FeedAdapter(this);
        rvFeed.setAdapter(feedAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        inboxMenuItem = menu.findItem(R.id.action_inbox);
        inboxMenuItem.setActionView(R.layout.menu_item_view);
        return true;
    }
}

运行结果:

Android Lollipop

Android pre-21

动画

最后一件也是最重要的事情就是进入时的动画效果,再浏览一遍概念视频,可以发现在main Activity启动的时候有如下动画,分成两步:

显示Toolbar以及其里面的元素

在Toolbar动画完成之后显示feed和floating action button。

Toolbar中元素的动画表现为在较短的时间内一个接一个的进入。实现这个效果的主要问题在于navigation icon的动画,navigation icon是唯一一个不能使用动画的,其他的都好办。

Toolbar animation

首先我们只是需要在activity启动的时候才播放动画(在旋转屏幕的时候不播放),还要知道menu的动画过程是不能在onCreate()中去实现的(我们在onCreateOptionsMenu()中实现),创建一个布尔类型的变量pendingIntroAnimation ,在onCreate()方法中初始化:

//...
if (savedInstanceState == null) {
    pendingIntroAnimation = true;
}

onCreateOptionsMenu():

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    inboxMenuItem = menu.findItem(R.id.action_inbox);
    inboxMenuItem.setActionView(R.layout.menu_item_view);
    if (pendingIntroAnimation) {
        pendingIntroAnimation = false;
        startIntroAnimation();
    }
    return true;
}

这样startIntroAnimation()将只被调用一次。

现在该来准备Toolbar中元素的动画了,也非常简单

ToolbarAnimation

//...
private static final int ANIM_DURATION_TOOLBAR = 300;

private void startIntroAnimation() {
    btnCreate.setTranslationY(2 * getResources().getDimensionPixelOffset(R.dimen.btn_fab_size));
    int actionbarSize = Utils.dpToPx(56);
    toolbar.setTranslationY(-actionbarSize);
    ivLogo.setTranslationY(-actionbarSize);
    inboxMenuItem.getActionView().setTranslationY(-actionbarSize);

    toolbar.animate()
        .translationY(0)
        .setDuration(ANIM_DURATION_TOOLBAR)
        .setStartDelay(300);
    ivLogo.animate()
        .translationY(0)
        .setDuration(ANIM_DURATION_TOOLBAR)
        .setStartDelay(400);
    inboxMenuItem.getActionView().animate()
        .translationY(0)
        .setDuration(ANIM_DURATION_TOOLBAR)
        .setStartDelay(500)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
            startContentAnimation();
            }
        })
        .start();
}
//...

在上面的代码中:

  • 首先我们将所有的元素都通过移动到屏幕之外隐藏起来(这一步我们将FAB也隐藏了)。
  • 让Toolbar元素一个接一个的开始动画
  • 当动画完成,调用了startContentAnimation()开始content的动画(FAB和feed卡片的动画)

简单,是吧?

Content 动画

在这一步中我们将让FAB和feed卡片动起来。FAB的动画很简单,跟上面的方法类似,但是feed卡片稍微复杂些。

startContentAnimation方法

//...
//FAB animation
private static final int ANIM_DURATION_FAB = 400;

private void startContentAnimation() {
    btnCreate.animate()
        .translationY(0)
        .setInterpolator(new OvershootInterpolator(1.f))
        .setStartDelay(300)
        .setDuration(ANIM_DURATION_FAB)
        .start();
    feedAdapter.updateItems();
}
//...

FeedAdapter的代码在上面已经贴出来了。结合着就知道动画是如何实现的了。

本篇文章就结束了,避免遗漏,这里是这篇文章是提交的代码commit for our project with implemented animations.

源代码

完整的代码在Github repository.

作者: Miroslaw Stanek

英文原文:Instagram with Material Design concept is getting real

还发表在这里:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2415.html

时间: 2024-10-28 23:01:31

实现Instagram的Material Design概念设计的相关文章

Instagram的Material Design概念设计文章分享

近期開始研究最新的Android 5 Material Design,一加氢OS公布后,非常快就有一大批支持Android5原生风格的手机出来了,你的App还是UI帮设计的吗?该考虑升级到 Material Design风格了, 这年头要与时俱进啊,不学习就out了. 这个系列的文章不错,给大家共享下 , 源代码Git地址  https://github.com/frogermcs/InstaMaterial InstaMaterial 概念设计(第九部分) - 图片的公布2015-05-09

实现Instagram的Material Design设计(2)- 评论窗口实现

实现Instagram的Material Design设计系列第一篇http://blog.csdn.net/tongsdroid/article/details/51567583 这篇文章是一个实现Instagram的Material Design设计系列的第二篇文章,今天,我们将实现主页和评论活动之间的过渡(在概念录像显示为9秒之间13).我们将跳过按钮效果(涟漪,发送完成动画等),只关注发表评论的Acitvity进入和退出动画. 这是在今天的文章中描述(适用于Android5.0和之前的版

Material Design 概念,环境和基本属性

Material Design 概念,环境和基本属性 Material Design是随Android 5.0推出的一种设计概念, 涉及到了跨平台和设备的视觉,动态,交互设计等方面. 设计概念 Material Design的灵感来自于对纸和墨水的研究,基于触觉现实感.并且它还在继续地发展扩充,有很大的想象空间. 基于现实,让材料的表面和边缘提供视觉线索. 熟悉的触觉属性可以帮助用户快速地明白正在发生什么. 光,表面和运动的一些基本规则是很关键性的因素,它们可以传达物体在空间如何存在,运动和交互

谷歌设计师的MATERIAL DESIGN实践心得

前不久,我们发布了Google I/O 2014 APP,源代码已经发布,诸位感兴趣的话,可以去Github看看我们是怎样在这个App中实现Material Design的功能和设计细节.在这篇文章中,我将分享一些我们对于Material Design的一些设计性思考. 每年Google I/O完了后,我们都会更新Google I/O相关的APP,我们做这个APP 有2个目的.第一,让那些在家看直播.甚至没有机会到现场的人更身临其境的了解Google I/O大会.第二,我们用Material D

【转】MATERIAL DESIGN设计规范学习心得

编者按:自学笔记就该这么做!今天分享@東門王三 同学关于Material Design的自学成果,他的学习笔记严谨有序,触类旁通,从Material Design到其他系统的设计规范都有所研究,还认真地做了思维导图,同学们可以边学习边借鉴他的自学方法,一举两得呦. 自学的一大重点就是读书,推荐同学们看一下华为设计总监的经验:<华为设计总监尤原庆:怎样读设计书> 想读好书的同学,可直接到:设计师图书导航 挑选. @東門王三 :随着Android系统从Android 4.4逐步升级到Android

开发 Material Design+RxJava+Retrofit+MVP App 参考资料

前言 在开发一个基于 Material Design+RxJava+Retrofit+MVP 框架的 App 过程中学习的资料整理 —— 由G军仔分享 这里记录了我开发 大象 项目时,所学习的开发资料以及参考的开源项目,稍微整理了一下,全当笔记记录,跟大家一起分享,也许能给正在使用 RxJava + Retrofit + MVP + Material Design 框架开发的人一个参考学习,如果有人从我分享的资料当中学习到东西,那是我的荣幸,希望大家能与我一起努力. 之前看到很多人都使用 RxJ

Material Design之RecyclerView的使用(一)

Android 5.0開始就推荐使用Material Design这个设计语言,本文開始就逐一解说Material Design中控件的使用.本章主要解说RecyclerView,期中会带有ToolBar的代码,也是一个Android5.x推荐使用ToolBar替代ActionBar的控件.RecyclerView 是 android-support-v7包中的一个控件,使用该控件时须要加入com.android.support:recyclerview-v7:22.2.0包依赖,该包可在我们下

Android Design 找设计灵感

借鉴下别人超棒的设计与体验 URL:http://huaban.com/boards/1091038/ URL:https://dribbble.com/ 充分的利用github,可以教你的设计师来用,找不同so easy URL:https://github.com/cameronmcefee/Image-Diff-View-Modes/commit/8e95f70c9c47168305970e91021072673d7cdad8 Android Material Design 统一设计语言规

Android Material Design之Toolbar与Palette

转:http://blog.csdn.net/jdsjlzx/article/details/41441083 前言 我们都知道Marterial Design是Google推出的全新UI设计规范,如果对其不太了解的可以看下:Material design非官方中文指导手册 ,或者我的前面几篇Material Design的译文,相比之前Google在Android Holo风格上平平淡淡的表现不同,Material Design现在是被Google所比较重视的.在推出这门全新设计语言后,And