开源项目Topeka的Material Design

项目配置

  1. minSdkVersion: 21 由于Material Design是随着Android5.0发布, 所以一般情况下支持的sdk最小版本为21, 如果要再5.0之前的系统使用, 可以参考Android开发者官网关于Material Desing兼容性的相关文章.
  2. 使用的依赖
    • compile 'com.android.support:cardview-v7:22.2.0'
    • compile 'com.android.support:recyclerview-v7:22.2.0'

项目结构

组件

该项目的AndroidManifest.xml中只有三个Activity.其中登陆界面是默认的启动界面.

<activity android:name=".activity.SignInActivity"
	    android:windowSoftInputMode="adjustPan">
	    <intent-filter>
		<action android:name="android.intent.action.MAIN" />
		<category android:name="android.intent.category.LAUNCHER" />
	    </intent-filter>
	</activity>

<activity android:name=".activity.CategorySelectionActivity" />

<activity android:name=".activity.QuizActivity"
	    android:parentActivityName=".activity.CategorySelectionActivity"
	    android:windowSoftInputMode="adjustPan" />

自定义Theme

该程序使用了自定义的Theme, 该Theme定义在style.xml文件中, 名称为Topeka.
<application
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="false"
    android:theme="@style/Topeka">
Topeka的实现, 先看下源码.
<style name="Topeka" parent="@android:style/Theme.Material.Light.NoActionBar">
    <item name="android:colorPrimary">@color/topeka_primary</item>
    <item name="android:colorPrimaryDark">@color/topeka_primary_dark</item>
    <item name="android:colorAccent">@color/topeka_accent</item>
    <item name="android:textColorPrimary">@android:color/black</item>
    <item name="android:textColorPrimaryInverse">@color/text_light</item>
    <item name="android:statusBarColor">@color/topeka_primary_dark</item>
    <item name="android:textColor">@color/text_dark</item>
    <item name="android:radioButtonStyle">@style/Topeka.CompoundButton.Radio</item>
    <item name="android:windowContentTransitions">true</item>
    <item name="android:titleTextAppearance">@style/Topeka.TextAppearance.Title</item>
    <item name="android:buttonStyle">@style/Topeka.CompoundButton</item>
    <item name="android:windowBackground">@color/light_grey</item>
</style>

可以看到该style继承了 Theme.Material.Light.NoActionBar 风格, 这事Material Design的一个风格. 同时应用也重写了该风格的一些属性:

Name  
colorPrimary 标题栏颜色
colorPrimaryDark 状态栏颜色
colorAccent 像是checkbox颜色?
textColorPrimary 标题栏字体
textColorPrimaryInverse  
statusBarColor 状态栏颜色
textColor 字体颜色
radioButtonStyle 自定义style
windowContentTransitions 动画转化效果
titleTextAppearance 自定义style
buttonStyle 自定义style
windowBackground window背景

重写的属性大部分都使用了单一的值, 只有radioButtonStyle/titleTextAppearance/buttonStyle这三个使用了 自定义的风格.自定义的style都放在drawable目录下.以radioButtonStyle为例

//style.xml
    <style name="Topeka.CompoundButton.Radio" parent="Topeka.CompoundButton">
	<item name="android:background">@drawable/selector_checkable</item>
    </style>

//res/drawable/selector_checkable.xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
    <item>
	<selector>
	    <item android:state_checked="false">
		<color android:color="?android:attr/colorButtonNormal" />
	    </item>
	    <item android:state_checked="true">
		<color android:color="?android:attr/colorPrimary" />
	    </item>
	</selector>
    </item>
</ripple>

ripple用于设置水纹效果.

登陆界面 SignInActivity.java

onCreate()

在onCreate函数中,直接通过FragmentManager启动一个SignInFragment的实例来显示登录界面.

SignInFragment

SignInFragment会在onCreateView中会判断是否需要登录, 如果不需要则直接进入CategoryActivity页面, 如果需要, 则显示登录信息, 输入登录信息后, 再跳转到CategoryActivity页面. 上述过程有两个地方用到了MaterialDesign的设计

Material Design 1: DonFab (Floating Button)

在SignInFragment中会让用户填写姓名和选择头像, 当用户填写完FirstName后, 左下角就会出现一个floating button, 点击即可进入Category Activity, 这个Floating Button即是Material Design的风格之一.

实现

SignInFragment中FloatingButton的具体实现为DoneFab类, 该类继承自 FloatingActionButton,后者也是该应用的 自定义view, 继承自ImageView.

public FloatingActionButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    setFocusable(true);
    setClickable(true);
    setOutlineProvider(new FabOutlineProvider());
    setClipToOutline(true);
    setScaleType(ScaleType.CENTER_INSIDE);
    setBackgroundResource(R.drawable.fab_background);
    setElevation(getResources().getDimension(R.dimen.elevation_fab));
}
  1. 在Material的主题中,通过设置view的elevation即可让主题呈现出阴影效果.
  2. 通过重写RoundOutlineProvider()函数来设置button的size大小.
  3. 通过使用自定义backgroundResource来设置按钮的水纹点击效果, holo_green_dark即为 水纹颜色.

    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@android:color/holo_green_dark">
        <item android:drawable="@android:color/white" />
    </ripple>

Material Design 2: 动画过渡

当输入完名称, 点击确定按钮时, 按钮的水纹效果完成后, 会进入CategoryActivity界面, 从视觉上来看, 确定按钮从登陆界面的右下角移动到了Category界面的左上角,并变成了头像. 这种控件在两个activity之间的 移动也是MaterialDesign的一种风格.

实现
  1. 当单击登录界面的确定按钮时, 会执行performSignInWithTransition()函数跳转到 CategoryActivity中.该函数的实现如下:

    private void performSignInWithTransition(View v) {
        Activity activity = getActivity();
        ActivityOptions activityOptions = ActivityOptions
    	    .makeSceneTransitionAnimation(activity, v,
    		    activity.getString(R.string.transition_avatar));
        CategorySelectionActivity.start(activity, mPlayer, activityOptions);
        activity.finishAfterTransition();
    }

    通过代码可以看到, 在启动activity时传入了一个ActivityOptions参数, 该参数是通过调用 makeSceneTransitionAnimation()生成.该函数接受三个参数:

    • activity: 包含 共享元素 的activity. 在这里即为SignInActivity.
    • view: 共享元素在activity中的值. 在这里即为SignInFragment中的确定按钮.
    • name: 目标activity中 共享元素 的transitionName值. 这里为CatogeryActivity中该名称的view.打开Category的layout文件可以找transitionName值为 name的值.可以看到该view即为category界面的头像.所以从登录界面跳刀category界面时, 右下角的登录按钮会 变化为左上角的头像按钮.

      <com.google.samples.apps.topeka.widget.AvatarView
          android:id="@+id/avatar"
          android:layout_width="@dimen/size_fab"
          android:layout_height="@dimen/size_fab"
          android:layout_marginEnd="@dimen/spacing_double"
          android:transitionName="@string/transition_avatar" />

Category界面

onCreate() and Layout

标题栏: toolbar

该activity的标题栏使用了Toolbar这个控件, 然后再onCreate()函数中通过调用 setActionBar(toolbar)将toolbar作为传统的actionbar使用.同时activity的 option menu也会添加到toolbar上.

最后在onCreate()里加载CategoryGridFragment的一个实例.

CategoryGridFragment

该fragment使用了GridView来显示目录列表.每个列表项由一个图片和文字构成. 使用到的gridview属性

   
drawSelectorOnTop 选中条目的时候颜色是否显示在上边
listSelector 选中条目时的可绘制对象
clipToPadding 如果ListView/GridView设置了paddingTop/Bottom. 该值为true,滚动时padding不会消失. false会消失.
scrollBarStyle outsideOverlay, 滚动时显示滚动条

listSelector同样使用了ripple风格. 通过设置mask的shape可以设置水纹的形状.

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/touch_effect">
    <item android:id="@android:id/mask">
	<shape android:shape="rectangle">
	    <solid android:color="@android:color/white" />
	</shape>
    </item>
</ripple>

Material Design 3: 多动画过渡

从category界面选中某一项会打开该类别的答题界面, 在页面切换过程中, 该项的文字栏会变成下一页的标题栏, 而头像会变成播放按钮.这种同时有多个 view进行动画过渡的效果是通过ActivityOptions.makeSceneTransitionAnimation() 函数实现的.

//find activity view
AvatarView avatarView = (AvatarView)getActivity().findViewById(R.id.lx_avatar);
// Create pair of transition participants.
List<Pair> participants = new ArrayList<>(3);
participants.add(new Pair<>(toolbar, activity.getString(R.string.transition_toolbar)));
participants.add(new Pair<>(avatarView, activity.getString(R.string.transition_avatar)));
@SuppressWarnings("unchecked")
ActivityOptions sceneTransitionAnimation = ActivityOptions
	.makeSceneTransitionAnimation(activity,
		participants.toArray(new Pair[participants.size()]));

// Starts the activity with the participants, animating from one to the other.
final Bundle transitionBundle = sceneTransitionAnimation.toBundle();
activity.startActivity(QuizActivity.getStartIntent(activity, category), transitionBundle);

在下一页的layout文件中设置了相应的transitionName

<com.google.samples.apps.topeka.widget.fab.FloatingActionButton
    android:id="@+id/fab_quiz"
    android:layout_width="@dimen/size_fab"
    android:layout_height="@dimen/size_fab"
    android:layout_gravity="bottom|end"
    android:layout_marginBottom="@dimen/spacing_double"
    android:layout_marginEnd="@dimen/spacing_double"
    android:transitionName="@string/transition_avatar" />  <---here---->

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

    <Toolbar
	android:id="@+id/toolbar_activity_quiz"
	android:layout_width="match_parent"
	android:layout_height="?android:attr/actionBarSize"
	android:layout_gravity="top"
	android:background="?android:colorPrimary"
	android:contentInsetStart="@dimen/spacing_huge"
	android:elevation="@dimen/elevation_header"
	android:navigationContentDescription="@string/up"
	android:navigationIcon="@drawable/ic_arrow_back"
	android:transitionName="@string/transition_toolbar"> <---here---->
    </Toolbar>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值