編輯:關於Android編程
Android 5.X UI設計初步 Android 5.X 新增特性分析這一章很多,但是很有趣,也是這書的最後一章知識點了,我現在還在考慮要不要寫這個拼圖和2048的案例,在此之前,我們先來玩玩Android5.X的新特性吧!
Android 5.X開始使用新的設計風格Material Design來統一整個Android系統設計風格,與之前的設計不同,這次的Material Design設計將Android帶來一片全新的高度,同時Google在官網推出了新的設計指南,全面的講解了Material Design的整個實現規范
材料的形態模擬是Material Design中最核心也是改變最大的設計,Google通過模擬自然界紙墨的形態變化,光線和陰影,紙和紙之間的空間層次關系,帶來一種真實的感覺
好的動畫效果可以非常的有效的指引用戶,暗示用戶並給用戶帶來愉悅的使用體驗,Android5.X中大量加入了各種新的動畫效果,讓整個設計風格更加自然,和諧,而各種新的轉場動畫,能更加有效的指引用戶的視覺焦點,不至於因為復雜布局的界面重排而對整體效果產生影響,讓使用者達到一個視覺連貫性
Material Design中用了大量高飽和度,適中亮度的大色塊來突出界面的主次,並一掃Android4.X系列Holo主題的沉重感,讓界面更加富有時尚感和視覺沖擊力
此外,還有更多的設計風格,比如懸浮按鈕,聚焦大圖,無框按鈕,波紋效果等新特性,這裡就不一一列舉了,Google在其Material Design網站上也有
我們先來看看如何使用主題,MD一共有三種默認的主題可以設置
@android:style/Theme.Material (dark version)
@android:style/Theme.Material.Light (light version)
@android:style/Theme.Material.Light.DarkActionBar
效果如圖
同時,Android5.X提出來Color Palette的概念,讓開發者可以設定系統區域的顏色,使得整個APP的顏色使得APP的顏色統一
通過如下所示的代碼,可以通過自定義style的方式來創建自己的ColZ喎?/kf/ware/vc/" target="_blank" class="keylink">vciBwYWxldHRl0dXJq9b3zOKjrLTTtvjKtc/W0dXJq7XEsrvNrLfnuPE8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8cHJlIGNsYXNzPQ=="brush:java;">
看效果
3.Palette
Vibrant(充滿活力的) Vibrant dark(充滿活力的黑) Vibrant light(充滿活力的白) Muted(柔和的) Muted dark(柔和的黑) Muted light(柔和的白)在Android的版本發展中,UI越來越成為Google的發展中心,這次的Android5.X創新的使用了Palette來提取顏色,從而讓主題能夠動態適應當前頁面的色調,使得整個app的顏色基本和諧統一
Android內置了幾種提取顏色的種類
使用Palette的API,能夠讓我們從Bitmap中獲取對應的色調,修改當前的主題色調,使用Palette首先需要在Android studio引用相關的依賴
compile 'com.android.support:palette-v7:21.0.+'
可以通過傳遞一個Bitmap對象給Palette,並調用它的Palette.generate()靜態方法或者Palette.generateAsync()方法創建一個Palette,接下來,就可以使用getter方法來檢索相應的色調,這些色調就是我們在上面列表所列出的色調
我們這裡寫一個小例子,演示如何通過加載的圖片的柔和色調來改變狀態欄和actionbar的色調,代碼如下
package com.lgl.materialdesign; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.graphics.Palette; import android.view.Window; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private ImageView iv_palette; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setPalette(); } /** * Palette獲取顏色 */ private void setPalette() { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); //創建Palette對象 Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { //通過Palette來獲取對應的色調 Palette.Swatch vibrant = palette.getDarkVibrantSwatch(); //將顏色設置給相應的組件 getSupportActionBar().setBackgroundDrawable(new ColorDrawable(vibrant.getRgb())); Window window = getWindow(); window.setStatusBarColor(vibrant.getRgb()); } }); } }
而且,我們可以使用不同的方法獲取不同的色調顏色
palette.getVibrantSwatch(); palette.getDarkMutedSwatch(); palette.getLightMutedSwatch(); palette.getMutedSwatch(); palette.getDarkVibrantSwatch(); palette.getLightVibrantSwatch();
看效果
4.視圖與陰影
Material Design的一個很重要的特點就是擬物扁平化,如果說IOS的扁平化設計太過於超前,讓很多人來不及從擬物轉變成扁平,那麼Material Design則是把IOS往回拉了一點,通過展現生活中的材料效果,恰當的使用陰影和光線,配合完美的動畫效果,模擬出一個動感十足又美麗大膽的視覺效果
-1.陰影效果
以往的Android View通常有兩個屬性——X和Y,而在Android5.X中,Google為其增加了一個新的屬性——Z,對應垂直方向上的高度變化,看圖,我們更加了解
在Android 5.X中,View的Z值由兩部分組成,elevation和translationZ(他們都是Android5.X新引入的屬性),elevation是靜態的成員,translationZ可以在代碼中使用來實現動畫效果,他們的關系
Z = elevation + translationZ;
通過下面的代碼,演示了不同視圖高度所顯示的效果,xml代碼
在程序中,我們也可以使用代碼改變視圖高度
view.setTranslationZ(xxx);
通常也會使用屬性動畫來為視圖高度改變的時候增加動畫效果
if(flag){ view.animate().translationZ(100); flag = false; }else { view.animate().translationZ(0); flag = true; }
5.Tinting 和 Clipping
Android5.X在對圖像的操作有了更多的功能,下面來看看Android5.X的兩個對操作圖像的新功能——Tinting(著色) 和 Clipping(裁剪)
-1.Tinting(著色)
Tinting的使用非常的簡單,只要在XML中配置好tint和tintMode就可以了,對於配置組合效果,只需要大家實際操作一下,就能非常清晰的理解處理效果,在下面的代碼中,設置了幾種不同的tint和tintMode效果,XML代碼如下
效果如下
Tint通過修改圖像的Alpha遮罩來修改圖像的顏色,從而達到重新著色的目的,這一功能在一些圖片處理的APP使用起來還是十分的方便的
-2. Clipping(裁剪)
Clipping可以讓我們改變一個視圖的外形,要使用Clipping,首先需要使用ViewOutlineProvider來修改outline作用給視圖
下面這個例子,將一個正方形的textview通過Clipping裁剪成一個圓形的正方形和一個圓,XML代碼如下
邏輯代碼很簡單
/** * Clipping裁剪 */ private void setClipping() { final View v1 = findViewById(R.id.tv_rect); View v2 = findViewById(R.id.tv_circle); //獲取Outline ViewOutlineProvider vlp1 = new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { //修改outline為特定形狀 outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 30); } }; //獲取Outline ViewOutlineProvider vlp2 = new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { //修改outline為特定形狀 outline.setOval(0, 0, view.getWidth(), view.getHeight()); } }; //重新設置形狀 v1.setOutlineProvider(vlp1); v2.setOutlineProvider(vlp2); }
我們看下效果
6.列表和卡片
-1.RecyclerView
在Android5.X中將使用了很久的ListView做了升級,增加了一個使用方便,效率更高的控件——RecyclerView,RecyclerView是support-v7中的一個新的組件,是一個強大的滑動控件,ViewHolder的封裝實現,用戶只要實現自己的viewholder就可以了,該組件會自動幫你回收服用的每一個item
要使用RecyclerView,首先需要在項目中引用依賴
compile 'com.android.support:recyclerview-v7:21.0.+'
在布局中使用RecyclerView與使用ListView基本類似,同樣需要一個類似List itemd的布局,在Material Design中,通常與CardView配合使用,後面我們再講CardView的使用
使用RecyclerView的重點和使用和ListView一樣,需要使用一個合適的數據適配器來加載數據,RecyclerView中需要重寫的很多方法都似曾相識,不過RecyclerView更加先進的是,它已經封裝好了ViewHolder,只要實現功能就可以,,先看Adapter
package com.lgl.materialdesign; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.TextView; import java.util.List; /** * RecyclerView的適配器 * Created by LGL on 2016/4/30. */ public class RecyclerAdapter extends RecyclerView.Adapter
{ private List mData; public RecyclerAdapter(List mData) { this.mData = mData; } public AdapterView.OnItemClickListener itemClickListener; public void setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) { this.itemClickListener = itemClickListener; } public interface OnItemClickListener { void onItemClic(View view, int position); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //將布局轉化為View並傳遞給RecyclerView封裝好的ViewHolder View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rc_item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { //建立起ViewHolder中視圖和數據的關聯 holder.textView.setText(mData.get(position) + position); } @Override public int getItemCount() { return mData.size(); } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private 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(null, v, getPosition(), R.id.tv_item); } } } } 上面就是一個非常簡單卻典型的RecyclerView,通過onCreateViewHolder將List item的布局轉換成View,並傳遞給RecyclerView封裝好的ViewHolder,就可以將數據和視圖關聯起來了,但是有一點要注意的是,Android並沒有給RecyclerView增進點擊事件,所以我們需要自己寫接口回調,代碼如圖
public AdapterView.OnItemClickListener itemClickListener; public void setOnItemClickListener(AdapterView.OnItemClickListener itemClickListener) { this.itemClickListener = itemClickListener; } public interface OnItemClickListener { void onItemClic(View view, int position); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //將布局轉化為View並傳遞給RecyclerView封裝好的ViewHolder View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rc_item, parent, false); return new ViewHolder(v); }
類似ListView的List item視圖
當然,僅僅是性能也是不夠的,讓開發者能夠更加方便的使用才是非常重要的,Google在RecyclerView中定義了LayoutManager來幫助開發者更加方便的創建不同但的布局,下面的例子就演示如何創建水平和垂直布局,當然,你也可以通過自定義LayoutManager來創建自己的布局,核心代碼如下:
mRcList.setLayoutManager(new LinearLayoutManager(this)); mRcList.setLayoutManager(new GridLayoutManager(this));
完整代碼:
package com.lgl.materialdesign; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.AdapterView; import android.widget.Spinner; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView mRcList; private RecyclerAdapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; private Spinner mSpinner; private List
mData = new ArrayList (); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRcList = (RecyclerView) findViewById(R.id.mRcList); 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(MainActivity.this)); }else if(position == 1){ //設置為表格布局 mRcList.setLayoutManager(new GridLayoutManager(MainActivity.this,3)); }else if(position == 2 ){ } } @Override public void onNothingSelected(AdapterView parent) { } }); //增加測試數據 mData.add("Android Test1"); mData.add("Android Test2"); mData.add("Android Test3"); mAdapter = new RecyclerAdapter(mData); mRcList.setAdapter(mAdapter); mAdapter.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(final AdapterView parent, View view, int position, long id) { //設置點擊動畫 parent.animate().translationZ(15f).setDuration(300).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); parent.animate().translationZ(1f).setDuration(500).start(); } }).start(); } }); } public void addRecycler(View view){ 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(); } } } 運行結果
-2.CardView
CardView曾經開始流行在Google+,後來越來越多的APP也引入了Card這樣的布局方式,說到底,CardView也是一個容器布局,只是他提供了一種卡片的形式,Google所幸提供了一個CardView控件,方便大家使用這種布局,開發者可以設置大小和視圖高度,圓角的角度等,在此之前,我們要添加依賴
compile 'com.android.support:cardview-v7:21.0.0+'
同時要添加命名空間
xmlns:app="http://schemas.android.com/apk/res-auto"
我們舉個例子
運行的效果
7.Activity過渡動畫
進入:一個進入的過渡動畫決定Activity中的所有視圖怎麼進入屏幕 退出:一個退出的過渡動畫決定Activity中的所有視圖怎麼退出屏幕 共享元素:一個共享元素過渡動畫決定兩個Activity之間的過渡,怎麼共享他們的視圖曾經的Android在activity進行跳轉的時候,只是很生硬的切換,即使通過 overridePendingTransition( int inId, int outId)這個方法來給Activity增加一些切換動畫,效果也只是差強人意,而在Android5.X中,Google對動畫效果進行了更深一步的诠釋,為Activity的轉場效果設計了更加豐富的動畫效果
Android5.X提供了三種Transition類型
explode(分解)一一從屏幕中間進或出,移動視圖 slide(滑動)——從屏幕邊緣進或出,移動視圖 fade(淡出) 一一通過改變屏幕上視圖的不透明度達到添加或者移除視圖其中,進人和退出效果包括
changeBounds——改變目標視圖的布局邊界 changeCliBounds——裁剪目標視圖邊界 changeTransfrom——改變目標視圖的縮放比例和旋轉角度 changeImageTransfrom——改變目標圖片的大小和縮放比例共享元素包括
可以發現,在Android5.X上,動畫效果的種類變得更加豐富了
首先來看看普通的三種Activity過渡動畫, 要使用這些動畫非常簡單,例如從ActivityA轉到ActivityB,只需要在ActivityA中將基本的startActivity(intent)方法改為如下代碼即可
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
而在AchvityB中,只需要設置下如下所示代碼
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
或者在樣式文件中設置如下所示代碼
- true
那麼接下來就可以設置進人/退出ActivityB的具體的動畫效果了, 代碼如下所示
getWindow().setEnterTransition(new Explode()); getWindow().setEnterTransition(new Slide()); getWindow().setEnterTransition(new Fade());
而對於共享元素的動畫效果.可以借用開發者網上的一張圖
要想在程序中使用共享元素的動畫效果也很簡單,首先需要在他的activity1布局中設置共享元素,增加元素代碼
android:transitionName="XXX"
同時在activity2中,也增加一個相應的共享元素屬性,如果只要一個共享元素,那麼在activity1中可以這樣寫
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this,view,"share").toBundle());
使用的參數就是前面普通動畫的基礎上增加了共享的的view和前面取的名字,如果由多個共享元素,那麼我們可以通過
Pair.create()
來創建多個共享元素
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view,"share"),Pair.create(fab,"fab")).toBundle());
下面我們通過一個具體的實例來演示一下過渡動畫,我們從BActivity跳轉到CActivity
BActivity的XML
實現邏輯
package com.lgl.materialdesign; import android.app.ActivityOptions; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Pair; import android.view.View; /** * BActivity * Created by lgl on 2016/5/1. */ public class BActivity extends AppCompatActivity { private Intent intent; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_b); } //設置不同的動畫效果 public void explode(View view) { intent = new Intent(this, CActivity.class); intent.putExtra("flag", 0); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); } //設置不同的動畫效果 public void slide(View view) { intent = new Intent(this, CActivity.class); intent.putExtra("flag", 1); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); } //設置不同的動畫效果 public void fade(View view) { intent = new Intent(this, CActivity.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, CActivity.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()); } }
再看CActivity的XML
實現邏輯就更簡單了
package com.lgl.materialdesign; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.transition.Explode; import android.transition.Fade; import android.transition.Slide; import android.view.Window; /** * CActivity * Created by LGL on 2016/5/2. */ public class CActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable 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; } setContentView(R.layout.activity_c); } }
我們運行一下就可以看到自己想要的效果了
八.Material Design動畫效果
動畫已經成了UI設計中一個非常重要的一個組成部分,在Android5.X的Material Design中,更是使用了大量的動畫效果,同時Google官方文檔也有詳細的說明
1.Ripple效果
在Android5.X中,Material Design大量的使用了Ripple動畫,即點就博文效果,可以通過如下代碼設置波紋的背景
//波紋有邊界 android:background="?android:attr/selectableItemBackground" //波紋無邊界 android:background="?android:attr/selectableItemBackgroundBorderless"
波紋有邊界是指波紋被限制在控件的邊界中,而波紋超出邊界,則是不會受到控件的限制,以圓形發散出去,我們做一個演示
XML
運行的效果
同樣的,我們可以寫一個xml文件來實現Ripple效果
使用方法直接設置背景就可以了,運行效果
2.Circular Reveal
這個動畫效果是在Google I/O 大會上演示了好多次的,具體變現為一個View以圓形的形式展開,揭示出來,通過ViewAnimationUtils.createCircularReveal()來創建動畫,代碼如下:
public static Animator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) { return new RevealAnimator(view,centerX,centerY,startRadius,endRadius); }
centerX 動畫開始的中心點X centerY 動畫開始的中心點Y startRadius 動畫開始半徑 endRadius 動畫結束半徑RevealAnimator的使用特別簡單,主要就是幾個關鍵的坐標點
我們還是通過一個實例去演示一下
XML
邏輯代碼
package com.lgl.materialdesign; import android.animation.Animator; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewAnimationUtils; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; /** * Circular Reveal * Created by LGL on 2016/5/2. */ public class CirActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_cir); 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(2000); 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(2000); animator.start(); } }); } }
這樣我們就可以去實現了
3. View state changes Animation
在Android5.X中,系統提供了視圖與狀態改變來設置一個視圖狀態的切換
StaetListAnimator
StaetListAnimator作為視圖改變時的動畫效果,通常會使用Seletor來進行設置,但是以前我們設置Seletor的時候,通常是修改他的背景來達到反饋的效果,但是再現在Android5.X中就不需要這樣了,可以使用動畫來實現,我們用小例子來具體看看怎麼實現的吧
在XML中定義一個StaetListAnimator
然後直接在布局中設置即可
animated-selector
animated-selector同樣是一個改變動畫效果的動畫,
這個效果不講,沒素材九.Toolbar
Toolbar和actionBar最大的區別就是Toolbar更加的自由,可控,這也是Google在逐漸使用Toolbar來取代actionBar的原因,要使用Toolbar就必須引用依賴
compile 'com.android.support:appcompat-v7:23.3.0'
同樣的,我們要設置主題
Theme.AppCompat.Light.NoActionBar
然後在XML中
在代碼中獲取
mToolbar = (Toolbar) findViewById(R.id.toolbar); mToolbar.setLogo(R.mipmap.ic_launcher); mToolbar.setTitle("主標題"); mToolbar.setSubtitle("副標題"); setSupportActionBar(mToolbar);
而menu都是一樣的,就不寫了,這樣一個title就寫出來了
我們再來具體實現以下,我們加入一個側滑的效果,XML代碼
然後我們設置一下
mToolbar = (Toolbar) findViewById(R.id.toolbar); mToolbar.setLogo(R.mipmap.ic_launcher); mToolbar.setTitle("主標題"); mToolbar.setSubtitle("副標題"); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer); mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar,0,0); mDrawerToggle.syncState(); mDrawerLayout.setDrawerListener(mDrawerToggle);
運行的效果
十.Notification
Notification作為一個時間觸發性的交互提示接口,讓我們獲得消息的時候,在狀態欄,鎖屏界面顯示相應的消息
Google在Android5.X中,又進一步的改進了通知欄,優化了Notification,在5.X設備上一個標准的通知是這樣的,長按是下圖
長按會顯示消息的來源
Notification會有一個從白色到灰色的動畫切換效果,最終顯示發出這個通知的調用者,而在我們的鎖屏界面,也可以看到
我們分四重境界來講解在Android5.X下使用Notification
1.基本的Notification
通過Notification.Builder創建一個Notification的builder,代碼如下
Notification.Builder builder = new Notification.Builder(this);
這個與AlertDialog的使用方法非常的相似,接下來,要點擊Notification執行一個intent,由於這個intent的不是立即執行,而是用戶觸發的,所以用pendingintent來完成這個延時操作,代碼如下:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.baidu.com")); //構造pendingdintent PendingIntent pendingIntent = PendingIntent.getActivities(this,0,intent,0);
這樣點擊PendingIntent 之後就會觸發時間了,我們也可以給他增加屬性
builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentIntent(pendingIntent); builder.setAutoCancel(true); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)); builder.setContentText("Title"); builder.setContentText("內容"); builder.setSubText("text");
通過下面的代碼發布通知欄
//通過NotificationManager來發出 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(0,builder.build());
這樣我們很輕松的就創建了一個通知欄
2.折疊式Notification
折疊式Notification也是一種自定義視圖的Notification,常常用於顯示文本,他擁有兩個視圖狀態,我們可以用RemoteView來幫助我們創建一個Notification視圖,代碼如下:
//通過RemoteViews創建自定義視圖 RemoteViews contentView = new RemoteViews(getPackageName(),R.layout.notification); contentView.setTextViewText(R.id.textView,"通知欄");
其中notification的布局是這樣的
通過如下代碼,可以講一個視圖指定為Notification正常狀態下的視圖
notification.contentView = contentView;
另一個展開的代碼
notification.bigContentView = expandedView;
奉獻完整代碼
package com.lgl.materialdesign; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.widget.RemoteViews; /** * Notification * Created by LGL on 2016/5/2. */ public class NotificationActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_notification); Notification.Builder builder = new Notification.Builder(this); Intent intents = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.baidu.com")); //構造pendingdintent PendingIntent pendingIntent = PendingIntent.getActivities(this, 0, new Intent[]{intents}, 0); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentIntent(pendingIntent); builder.setAutoCancel(true); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)); //通過RemoteViews創建自定義視圖 RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notification); contentView.setTextViewText(R.id.textView, "通知欄"); Notification notification = builder.build(); //指定視圖 notification.contentView = contentView; RemoteViews expandedView = new RemoteViews(getPackageName(), R.layout.notification_expanded); notification.bigContentView = expandedView; //通過NotificationManager來發出 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(0, builder.build()); } }
3.懸掛式Notification
懸掛式Notification是Android5.X新增加的方式,Google希望通過這個方式來給用戶帶來更好的體驗,這種被稱為Headsup的Notification方式,可以在屏幕的上方產生Notification而不打擾用戶的操作
在Android Sample中,Google給我們展示了這個項目,代碼如下:
Notification.Builder builder = new Notification.Builder(this).setSmallIcon(R.mipmap.ic_launcher).setPriority(Notification.PRIORITY_DEFAULT).setCategory(Notification.CATEGORY_MESSAGE).setContentTitle("Headsup Notification").setContentText("I am Headsup Notification"); Intent push = new Intent(); push.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); push.setClass(this,MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivities(this,0, new Intent[]{push},PendingIntent.FLAG_CANCEL_CURRENT); builder.setContentText("Android 5.X Headsup Notification").setFullScreenIntent(pendingIntent,true); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.notify(0,builder.build());
效果
4.顯示等級的Notification
VISIBILITY_PRIVATE -沒有鎖屏的時候顯示 VISIBILITY_PUBLIC - 表明在任何情況下都會顯示 VISIBILITY_SECRET - 表明在pin,password等安全鎖和沒有鎖屏的情況下顯示最後一重境界也就是新加入的一種模式,顯示登記,具體分三級
這一章自我感覺沒啥寫的,就一頁,跳過吧,很少的知識點
群英傳到這裡,也就沒有知識點可以將了,最後十三章,是兩個小項目,本來不准備講的,不過看到這個拼圖還是可以講一講的,就准備寫了,2048我很早之前就寫過,這裡就不重復了
自定義開關控件 Android自定義控件一般有三種方式 1、繼承Android固有的控件,在Android原生控件的基礎上,進行添加功能和邏輯。 2、繼承Vie
沒有使用第三方類庫,純代碼定制.主要用到的知識如下,我們知道,不管是自定義View還是系統提供的TextView這些,它們都必須放置在LinearLayout等一些Vie
ContentProvider,從字面意義上理解,內容提供者,這個類目的就是一個橋梁的作用,讓一個應用的數據(SQLiteDatabase, SharedPreferen
package xiaosi.location; import android.app.Activity; import android.os.Bund