初心者〜中級者 android studioによるandroid勉強会資料(スライド)
TRANSCRIPT
初級~中級者向け Android勉強会GDG神戸@ECCコン専スマートフォン研究会
夜子まま(@yokmama)2015.5.23
講義内容
Android StudioについてHello World~デバッグ迄
Material DesignについてTheme~Animation迄
Android StudioAndroid StudioによるAndroidアプリの作成
Hello Worldを作ってみよう
プロジェクトの新規作成
新規プロジェクト
プロジェクト名入力
Android SDKの設定
雛形の選択
空のプロジェクト
初期画面
プロジェクトを確認
クリック
クリック クリック
空のActivityを作成
appの箇所を選択しコンテキストメニューを呼び出す
Activityの設定
生成されたもの
・MainActivity.java ・res/activity_main.xml ・res/menu_main.xml ・res/strings.xml ・AnroidManifest.xml ・(初回)dimens.xml、style.xml
起動用アプリを設定
追加
アプリを実行クリック
レイアウトを編集してみよう
レイアウトエディタを開く
ダブルクリック
ダブルクリック
編集モード切り替え
Design XML
Buttonを配置
ドラッグ&ドロップ
Buttonのラベルを変更
変更を確認
プログラムを編集してみよう
Javaプログラムを開く
クリックダブルクリック
ダブルクリック
プログラムを編集
動作を確認
クリック
ビルドをしてみよう
build.gradleを開く
ダブルクリック
ビルドバージョンを変更
ビルドを実行
クリック クリック ダブルクリック
デバッグをしてみよう
バグを追加
バグ
バグを確認
※注)buildを実行した後だと設定が変更されているので注意
ブレークポイントを設定
クリック
デバッグ実行
ステップ実行
クリック
マウスホバー
デバッグ終了
クリック
Material DesignMaterial DesignによるAndroidアプリの作成
Material Themeを使ってみよう
lesson30/beforeのサンプルを開く
サンプルを実行
appcompat-v7の参照を追加
app/build.gradle
ActivityをAppCompatActivityに変更ItemDetailActivity
ItemListActivity
ThemeをThme.AppCompatに変更styles.xml
colorPrimaryとcolorPrimaryDarkを追加styles.xml
サンプルを実行
Toolbarを使ってみよう
lesson31/beforeのサンプルを開く
サンプルを実行
Toolbarをレイアウトに追加<RelativeLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
…省略
<!-- Toolbarを常にScrollViewの上に表示するためScrollViewの後に定義する--> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:elevation="5dp"/> </RelativeLayout>
activity_main.xml
Toolbarを使うためにThemeを変更
styles.xml
ToolbarをActionBarとして振る舞うように設定
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mScrollView = (ScrollView) findViewById(R.id.scrollView); //Toolbarのインスタンスを取得 mToolbar = (Toolbar) findViewById(R.id.toolbar); //ToolbarをActionbarとして設定 setSupportActionBar(mToolbar); //Toolbarのアイコンを設定 mToolbar.setLogo(R.mipmap.ic_launcher); //Toolbarのタイトルを設定 mToolbar.setTitle("タイトル名"); //Toolbarのサブタイトルを設定 mToolbar.setSubtitle("サブタイトル名"); …省略}
MainActivity
ToolbarをScrollViewと連動
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);…省略 mTypedArray.recycle();mScrollView.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener);
…省略}
MainActivity
ToolbarをScrollViewと連動
/** * パラメータに一致する画像、あるいはNULLの場合は全ての画像を一覧に追加 * * @param searchName */ private void updateList(String searchName) {…省略 contents.removeAllViews(); //ヘッダー用の空白を追加 View brankHeader = new View(this); brankHeader.setMinimumHeight((int) mToolbarBarHeight); contents.addView(brankHeader, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); //17個の画像をScrollViewのItemとして追加 for (int i = 1; i <= 21; i++) {…省略 }
MainActivity
ToolbarをScrollViewと連動
/** * ScrollViewのスクロール変化時の処理 */private ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() { private boolean isHide = false; @Override public void onScrollChanged() { float y = mScrollView.getScrollY(); if (y >= mToolbarBarHeight && !isHide) { isHide = true; mToolbar.animate() .translationY(-mToolbar.getBottom()) .setInterpolator(new DecelerateInterpolator()); } else if (y == 0 && isHide) { isHide = false; mToolbar.animate().translationY(0); } }};
MainActivity
サンプルを実行
Paletteを使ってみよう
lesson32/beforeのサンプルを開く
サンプルを実行
Themeの色を設定styles.xml
Paletteライブラリの参照を追加
app/build.gradle
画像のPalette解析を実装 @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);…省略 imageView.setImageResource(resId); //画像のパレットを解析 Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); Palette.Builder builder = new Palette.Builder(bitmap); builder.generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(Palette palette) { // Mutedな色情報を取得してToolbarにセット Palette.Swatch muted = palette.getMutedSwatch(); if (muted != null) { mToolbar.setBackgroundColor(muted.getRgb()); TextView tvTitle = (TextView) findViewById(R.id.textTitle); tvTitle.setTextColor(muted.getTitleTextColor()); //ステータスバーのカラーを変更(Lollipop以降のみ動作) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.addFlags( WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.setStatusBarColor(muted.getRgb()); } } //カラーブロックをセット setPalletBlock(palette.getLightVibrantColor(Color.TRANSPARENT), R.id.viewPalette1); setPalletBlock(palette.getVibrantColor(Color.TRANSPARENT), R.id.viewPalette2); setPalletBlock(palette.getDarkVibrantColor(Color.TRANSPARENT), R.id.viewPalette3); setPalletBlock(palette.getLightMutedColor(Color.TRANSPARENT), R.id.viewPalette4); setPalletBlock(palette.getMutedColor(Color.TRANSPARENT), R.id.viewPalette5); setPalletBlock(palette.getDarkMutedColor(Color.TRANSPARENT), R.id.viewPalette6); } });}
PaletteActivity
画像のPalette解析を実装
/** * 指定したViewにカラーをセット(色がない場合は非表示). * * @param color カラー * @param viewId ビューID */private void setPalletBlock(int color, int viewId) { View view = findViewById(viewId); if (color == Color.TRANSPARENT) { view.setVisibility(View.GONE); } else { view.setBackgroundColor(color); }}
PaletteActivity
サンプルを実行
RecyclerViewを使ってみよう
lesson33/beforeのサンプルを開く
RecyclerViewの参照を追加
app/build.gradle
RecyclerViewを使うようレイアウトを変更
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"…省略 </RadioGroup> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/></LinearLayout>
main_activity.xml
ListViewをRecyclerViewに変更
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<BaseItem>> { private RecyclerView mRecyclerView; …省略 private RecyclerView.ItemDecoration mItemDecoration; @Override protected void onCreate(Bundle savedInstanceState) {…省略 mListType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { getSupportLoaderManager().restartLoader(0, null, MainActivity.this); } }); mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);…省略 }
MainActivity
ViewHolderをRecyclerViewに対応
public class ImageViewHolder extends RecyclerView.ViewHolder{ private ImageView mImageView; private TextView mTextView; public ImageViewHolder(View itemView) { super(itemView); mImageView = (ImageView)itemView.findViewById(R.id.imageView); mTextView = (TextView)itemView.findViewById(R.id.textView); }…省略 }
ImageViewHolder
AdapterをRecyclerViewに対応 public class MyListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; …省略
@Override public int getCount() { …省略 }
@Override public Object getItem(int position) { …省略 }
@Override public long getItemId(int position) { …省略 }
@Override public View getView(int position, View convertView, ViewGroup parent) { …省略 }
@Override public int getItemViewType(int position) { …省略 } }
MyListAdapter
削除
AdapterをRecyclerViewに対応
public class MyListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; …省略 @Overridepublic int getItemViewType(int position) { return mItems.get(position).getType();} …省略
MyListAdapter
AdapterをRecyclerViewに対応
public class MyListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; …省略 @Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) { if(type == R.id.index_type){ return new IndexViewHolder(mLayoutInflater.inflate(R.layout.index_row, viewGroup, false)); }else{ return new ImageViewHolder(mLayoutInflater.inflate(R.layout.list_row, viewGroup, false)); }}
…省略
MyListAdapter
AdapterをRecyclerViewに対応
public class MyListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; …省略 @Overridepublic void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { BaseItem item = mItems.get(position); if(item.getType() == R.id.index_type){ IndexItem indexItem = (IndexItem)item; IndexViewHolder indexViewHolder = (IndexViewHolder)viewHolder; indexViewHolder.getTextView().setText(indexItem.getName()); }else{ ImageItem imageItem = (ImageItem)item; ImageViewHolder imageViewHolder = (ImageViewHolder)viewHolder; imageViewHolder.getTextView().setText(imageItem.getName()); imageViewHolder.getImageView().setImageResource(imageItem.getId()); }}
…省略
MyListAdapter
AdapterをRecyclerViewに対応
public class MyListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; …省略 @Overridepublic int getItemCount() { if(mItems!=null) { return mItems.size(); }else{ return 0; }}
…省略
MyListAdapter
RecyclerViewに罫線を追加
private void updateAdapter() { if (mListType.getCheckedRadioButtonId() == R.id.radioList) { mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); //RecyclerViewに罫線を設定 mItemDecoration = new DividerItemDecoration(getResources()); //Dividerが設定されていなければ設定 if (mItemDecoration == null) { mItemDecoration = new DividerItemDecoration(getResources()); mRecyclerView.addItemDecoration(mItemDecoration); } //ListViewスタイルのAdapetrを設定 mRecyclerView.setAdapter(new MyListAdapter(this, mItems)); }}
MainActivity
RecyclerViewに罫線を追加
private void updateAdapter() { if (mListType.getCheckedRadioButtonId() == R.id.radioList) { …省略 } else if (mListType.getCheckedRadioButtonId() == R.id.radioGrid) { mRecyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(), 3)); //グリッドの個数返却処理 ((GridLayoutManager) mRecyclerView.getLayoutManager()).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int i) { int type = mRecyclerView.getAdapter().getItemViewType(i); if (type == R.id.index_type) { return ((GridLayoutManager) mRecyclerView.getLayoutManager()).getSpanCount(); } else { return 1; } } }); //Dividerが設定されていれば解除 if (mItemDecoration != null) { mRecyclerView.removeItemDecoration(mItemDecoration); mItemDecoration = null; } //GridViewスタイルのAdapetrを設定 mRecyclerView.setAdapter(new MyGridAdapter(this, mItems)); }}
MainActivity
RecyclerViewに罫線を追加
private void updateAdapter() { if (mListType.getCheckedRadioButtonId() == R.id.radioList) { …省略 } else if (mListType.getCheckedRadioButtonId() == R.id.radioGrid) {…省略 } else { mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); //Dividerが設定されていれば解除 if (mItemDecoration != null) { mRecyclerView.removeItemDecoration(mItemDecoration); mItemDecoration = null; } //千鳥状スタイルのAdapetrを設定 mRecyclerView.setAdapter(new MyStaggeredAdapter(this, mItems)); }}
MainActivity
RecyclerViewにクリック処理を設定
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); …省略 mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); //RecyclerViewにクリック処理とロングクリック処理を設定 mRecyclerView.addOnItemTouchListener(new ItemClickListener(mRecyclerView) { @Override boolean performItemClick(RecyclerView parent, View view, int position, long id) { BaseItem item = mItems.get(position); Toast.makeText(MainActivity.this, "Click " + item.getName(), Toast.LENGTH_SHORT).show(); return false; } @Override boolean performItemLongClick(RecyclerView parent, View view, int position, long id) { BaseItem item = mItems.get(position); Toast.makeText(MainActivity.this, "Long Click " + item.getName(), Toast.LENGTH_SHORT).show(); return false; } });…省略}
MainActivity
サンプルを実行
Animationを使ってみよう
lesson34/beforeのサンプルを開く
View Animation(Activity)
画面遷移のAnimationを作成
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="100%" android:toXDelta="0%" /></set>
anim/activity_open_enter.xml
画面遷移のAnimationを作成
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="0%" android:toXDelta="-100%" /></set>
anim/activity_open_exit.xml
画面遷移のAnimationを作成
<?xml version="1.0" encoding="utf-8"?><!--Activity2の終了時のアニメーション--><set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="0%" android:toXDelta="100%" /></set>
anim/activity_close_exit.xml
画面遷移のAnimationを作成
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="-100%" android:toXDelta="0%" /></set>
anim/activity_close_enter.xml
画面遷移のAnimationを追加
<!-- Translate Animation --><style name="Lesson34.Animation.Translate" parent="android:Animation.Activity"> <item name="android:activityOpenEnterAnimation">@anim/activity_open_enter</item> <item name="android:activityOpenExitAnimation">@anim/activity_open_exit</item> <item name="android:activityCloseExitAnimation">@anim/activity_close_exit</item> <item name="android:activityCloseEnterAnimation">@anim/activity_close_enter</item> </style> <style name="Lesson34.TranslateAnimation" parent="AppTheme"> <item name="android:windowAnimationStyle">@style/Lesson34.Animation.Translate</item> </style>
values/styles.xml
画面遷移のAnimationを設定
<activity android:name=".ui.TranslateAnimationActivity" android:label="@string/app_name" android:theme="@style/Lesson34.TranslateAnimation" />
AndroidManifest.xml
View Animation(Dialog)
Dialog開閉時のAnimationを作成
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="100%" android:toXDelta="0%" /> <alpha android:duration="300" android:toAlpha="1.0" android:fromAlpha="0.0" /></set>
anim/fragment_open_enter.xml
Dialog開閉時のAnimationを作成
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:duration="300" android:fillAfter="true" android:fillEnabled="true" android:fromXDelta="0%" android:toXDelta="-100%" /> <alpha android:duration="300" android:toAlpha="0.0" android:fromAlpha="1.0" /></set>
anim/fragment_open_exit.xml
Dialog開閉時のAnimationを追加
<style name="Lesson34.Animation.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert"> <item name="android:windowAnimationStyle">@style/Lesson34.Animation.Window</item> <item name="android:windowBackground">@android:color/transparent</item> </style> <style name="Lesson34.Animation.Window" parent="android:Animation.Dialog"> <item name="android:windowEnterAnimation">@anim/fragment_open_enter</item> <item name="android:windowExitAnimation">@anim/fragment_open_exit</item> </style>
values/styles.xml
<!-- Translate Animation --><style name="Lesson34.Animation.Dialog" parent="android:Theme.Material.Light.Dialog.Alert"> <item name="android:windowAnimationStyle">@style/Lesson34.Animation.Window</item> </style>
values-v21/styles.xml
Dialog開閉時のAnimationを利用するDialogを実装
@Overridepublic void onClick(View v) { int id = v.getId(); if (id == R.id.button) { Intent intent = new Intent(TranslateAnimationActivity.this, TranslateAnimationActivity.class); startActivity(intent); } else if (id == R.id.btn_fragment) { TranslateAnimationDialogFragment f = new TranslateAnimationDialogFragment(); f.show(getSupportFragmentManager(), "TranslateAnimationDialogFragment"); }}
TranslateAnimationActivity
Dialog開閉時のAnimationを利用するDialogを実装
package com.yokmama.learn10.chapter07.lesson34.ui;import android.app.AlertDialog;import android.app.Dialog;import android.content.DialogInterface;import android.os.Bundle;import android.support.v4.app.DialogFragment;import com.yokmama.learn10.chapter07.lesson34.R;public class TranslateAnimationDialogFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.Lesson34_Animation_Dialog); builder.setTitle("タイトル") .setMessage("メッセージ") .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dismissAllowingStateLoss(); } }); return builder.create(); }}
TranslateAnimationDialogFragment
Property Animation
Property Animationを追加
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:duration="400" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="0.0" /> <objectAnimator android:duration="400" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="0.0" /></set>
animator/activity_property_animation_grid_hide.xml
Property Animationを追加
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:duration="400" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="scaleX" android:valueFrom="0.0" android:valueTo="1.0" /> <objectAnimator android:duration="400" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="scaleY" android:valueFrom="0.0" android:valueTo="1.0" /></set>
animator/activity_property_animation_grid_show.xml
Property Animationを追加
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially"> <objectAnimator android:duration="500" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="translationX" android:valueFrom="0" android:valueTo="500" /> <objectAnimator android:duration="500" android:interpolator="@android:interpolator/decelerate_quint" android:propertyName="translationX" android:valueFrom="500" android:valueTo="0" /></set>
animator/activity_property_animation_move_x.xml
Property Animationを利用するViewを実装
/** GridLayout のアニメーション */private void doAnimationToGridLayout() { for (int i = 0, iL = mGridLayout.getChildCount(); i < iL; i++) {…省略 // childを読み込み View childAt = mGridLayout.getChildAt(i); // アニメーション読み込み、設定 Animator anim = (isShowingGridLayout) ? AnimatorInflater.loadAnimator(this, R.animator.activity_property_animation_grid_hide) : AnimatorInflater.loadAnimator(this, R.animator.activity_property_animation_grid_show); anim.setTarget(childAt); anim.setStartDelay(dist * 60); anim.start(); } isShowingGridLayout = !isShowingGridLayout; }
PropertyAnimationActivity
Activity Transition
Activity Transitionを追加
<style name="Lesson34.Transition.Fade" parent="Lesson34.Transition"> <item name="android:windowEnterTransition">@android:transition/fade</item> <item name="android:windowExitTransition">@android:transition/fade</item> </style> <style name="Lesson34.Transition.Slide" parent="Lesson34.Transition"> <item name="android:windowEnterTransition">@android:transition/slide_right</item> <item name="android:windowExitTransition">@android:transition/slide_left</item> </style> <style name="Lesson34.Transition.Explode" parent="Lesson34.Transition"> <item name="android:windowEnterTransition">@android:transition/explode</item> <item name="android:windowExitTransition">@android:transition/explode</item> </style>
values-v21/styles.xml
Activity Transitionを使用するようThemeに設定
<style name="Lesson34.Transition" parent="AppTheme"> <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">true</item> <item name="android:windowContentTransitions">true</item> </style>
values-v21/styles.xml
Activity Transitionを設定したThemeをActivityに設定
<activity android:name=".ui.TransitionsFadeActivity" android:theme="@style/Lesson34.Transition.Fade" android:label="@string/app_name" /><activity android:name=".ui.TransitionsExplodeActivity" android:theme="@style/Lesson34.Transition.Explode" android:label="@string/app_name" /><activity android:name=".ui.TransitionsSlideActivity" android:theme="@style/Lesson34.Transition.Slide" android:label="@string/app_name" />
AndroidManifest.xml
Activity Transitionを使うよう、startActivityを変更
@Overrideprotected void onCreate(Bundle savedInstanceState) {…省略 // 一覧の作成 final ArrayAdapter<Activities> adapter = new ArrayAdapter<Activities>( this, android.R.layout.simple_list_item_1, Activities.values());…省略 // Intent発行 Intent intent = new Intent(MainActivity.this, item.activityClass); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this); ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle()); } });}
MainActivity
Shared Elementを設定<string name="transition_name_fab">fab</string>
values/strings.xml
<FrameLayout android:layout_width="match_parent" android:layout_height="@dimen/activity_transition_toolbar_height" android:layout_alignParentTop="true" android:layout_centerHorizontal="true"> <Button android:id="@+id/action" style="@style/fab" android:layout_gravity="center" android:transitionName="@string/transition_name_fab" /></FrameLayout>
layout-v21/activity_transition_after.xml
Shared Elementを設定
protected void onClickCircleButton(@IdRes Button buttonView, @ColorRes int colorPrimaryResId, @ColorRes int colorPrimaryDarkResId, @DrawableRes int backgroundResId) { // 遷移先渡す情報をIntentに詰める Intent intent = new Intent(this, TransitionsAfterActivity.class); intent.putExtra(TransitionsAfterActivity.EXTRA_COLOR_PRIMARY_ID, colorPrimaryResId); intent.putExtra(TransitionsAfterActivity.EXTRA_COLOR_PRIMARY_DARK_ID, colorPrimaryDarkResId); intent.putExtra(TransitionsAfterActivity.EXTRA_BACKGROUND_ID, backgroundResId); // 遷移先の android:transitionName とマッチする ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( this, buttonView, getString(R.string.transition_name_fab)); ActivityCompat.startActivity(this, intent, options.toBundle());}
TransitionBaseActivity
Transition Animationの作成
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeBounds android:duration="600" android:interpolator="@android:interpolator/anticipate_overshoot"/></transitionSet>
transition-v21/activity_transitions.xml
遷移後のActivityniActivity Transitionを使用するようThemeに設定
<style name="Lesson34.TransitionAfter" parent="AppTheme"> <item name="windowActionBar">false</item> <item name="windowActionModeOverlay">true</item> <item name="android:windowSharedElementEnterTransition">@transition/activity_transitions</item> <item name="android:windowSharedElementExitTransition">@transition/activity_transitions</item> </style>
values-v21/styles.xml
Transition Animationの連携@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void doRevealEffect() { // RevealEffectは、ビューのサイズが計算されたタイミング以降でしか呼び出せない // そのため、ビューが計算されるまで待つ ViewUtils.callOnLayout(mToolbar, new ViewUtils.OnLayoutCallback<Toolbar>() { @Override public void onLayout(Toolbar view) { // Reveal Effect を実施 int centerX = view.getWidth() / 2; int centerY = view.getHeight() / 2; float startRadius = 0; float endRadius = (float) Math.hypot(centerX, centerY); Animator animator = ViewAnimationUtils.createCircularReveal( view, centerX, centerY, startRadius, endRadius); // 緩急の指定 Interpolator interpolator = AnimationUtils.loadInterpolator(getApplicationContext(), android.R.interpolator.accelerate_cubic); animator.setInterpolator(interpolator); // アニメーション開始 animator.start(); } });}
TransitionsAfterActivity
Fragment Transition
FragmentのTransitionを追加
<!-- Fragment Transitions --><style name="Lesson34.FragmentTransitions" parent="AppTheme"> <item name="android:windowContentTransitions">true</item> </style>
values-v21/styles.xml
Fragment Transitionを設定したThemeをActivityに設定
<activity android:name=".ui.FragmentTransitionsActivity" android:label="@string/app_name" android:theme="@style/Lesson34.FragmentTransitions" />
AndroidManifest.xml
Transition Animationを設定
@Overridepublic void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Transitionsを生成 TransitionInflater ti = TransitionInflater.from(getActivity()); // 指定されたタイプの Transitions を設定 int viewId = getArguments().getInt(EXTRA_TRANSITIONS_TYPE_VIEW_ID); if (viewId == R.id.btn_add_fragment_explode) { setEnterTransition(ti.inflateTransition(android.R.transition.explode)); setExitTransition(ti.inflateTransition(android.R.transition.explode)); } else if (viewId == R.id.btn_add_fragment_fade) { setEnterTransition(ti.inflateTransition(android.R.transition.fade)); setExitTransition(ti.inflateTransition(android.R.transition.fade)); } else if (viewId == R.id.btn_add_fragment_slide) { setEnterTransition(ti.inflateTransition(android.R.transition.slide_left)); setExitTransition(ti.inflateTransition(android.R.transition.slide_right)); } else { // "NONE"押下時。この場合何もセットしない } }
FragmentTransitionsFragment
サンプルを実行
Lollipop専用
質問コーナー
Google IO ExtendedI/O Extended は、開発者の皆さんが集まり、一緒に Google I/O のライブ ストリームを視聴するイベントです。すでに世界各地 100 箇所を超える場所で I/O Extended が企画されており、近くで開催される予定がない場合は I/O Extended オーガナイザー用の企画サイトを見て、自分で企画することも可能です。
<京都会場の概要>
名称: Google I/O Extended Kyoto ( Google I/O 2015 を町家で観る会) 日時:2015 年 5 月 28 日(木) 20:30 - 5 月 29 日(金)8:00 (受付 5 月 28 日 20:00 - 20:30) 主催: GDG 京都 協力: Google 後援: 京都リサーチパーク株式会社 会場: KRP 町家スタジオ (京都市上京区葭屋町通中立売上る福大明神町 128) 会費: 無料 参加資格: Google I/O 2015 に興味のある 20 歳以上の方 定員: 20 名
<神戸会場の概要>
名称: I/O Extended 2015 Kobe 主催: GDG 神戸 協力: Google 会場:BAR YUME-YA ZERO (神戸市中央区北長狭通 2 丁目 31 - 55) 日時:2015 年 5 月 28 日(木) 23:00 - 5 月 29 日(金)8:00 会費: 無料(飲食代は個別清算)※別途ワンドリンク注文必要。 参加資格: Google I/O 2015 に関心がある方 ※未成年の方は保護者同伴でお願い致します。深夜帯ですので、何か問題が発生した場合でも、GDG 神戸では責任を負いかねます。 定員: 20 名
5月28日の夜~
申し込み(京都) https://goo.gl/6TETWu
申し込み(神戸) https://goo.gl/ro67EG