初心者〜中級者 Android StudioによるAndroid勉強会資料(スライド)

Preview:

Citation preview

初級~中級者向け 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

Recommended