Honeycombチュートリアル その4
手順
- string.xmlの変更
- add photo_selection_cab_title
- ActionModeのためのメニューを作成する
- menuレイアウトの作成
- photo_context_menu.xml
- menuレイアウトの作成
- ContentFragmentの修正
- フィールドの追加
- private ActionMode currentActionMode;
- private ActionMode.Callback mContentSelectionActionModeCallback
- ActionMode.Callbakの作成
- onPrepareActionMode
- onCreateActionMode
- onCreateViewメソッドの修正
- setOnLongClickListenreの追加
- フィールドの追加
ActionModeとは
アクションモードは、コンテンツをモーダルインタラクションのために使用され、終了するまで、通常のUIの部分を置き換えることができます。
string.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">HoneycomicGallery</string> <string name="photo_selection_cab_title">Photo selection</string> </resources>
photo_context_menu.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:title="Share" android:icon="?attr/menuIconShare" android:id="@+id/share" android:showAsAction="always|withText"></item> </menu>
ContentFragment.java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
フィールドの追加
現在のアクションモードとActionModeのコールバックを生成
private ActionMode currentActionMode; private ActionMode.Callback mContentSelectionActionModeCallback
ActionMode.Callback の作成
ActionModeのためのコールバックインタフェース
アクションモードとユーザーの相互作用によって発生したイベントを処理します。
- onCreateActionMode(ActionMode, Menu)
- 最初に作成された時だけ呼ばれる
- onPrepareActionMode(ActionMode, Menu)
- 作成後とActionModeになる直前と無効化時に、アクションモードのアクションメニューをリフレッシュするために呼び出されます。
- onActionItemClicked(ActionMode, MenuItem)
- Actionボタンを押した時
- onDestroyActionMode(ActionMode)
- AnctionModeを終了するとき
private ActionMode.Callback contentSelectionActionCallback = new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { contentView.setSelected(false); currentActionMode = null; } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.setTitle(R.string.photo_selection_cab_title); MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.photo_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.share: shareCurrentPhoto(); mode.finish(); return true; } return false; } };
ロングクリック時の処理
contentViewにOnLongClickListenterの実装
ロングクリック時にActionModeを開始する
- public ActionMode startActionMode (ActionMode.Callback callback)
- ActionModeを開始する
- 引数にActionModeイベントのコールバックリスナを設定する
// When long-pressing a photo, activate the action mode for selection, showing the // contextual action bar (CAB). contentView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { if(currentActionMode != null){ return false; } currentActionMode = getActivity().startActionMode(contentSelectionActionCallback); contentView.setSelected(true); return true; } }); // TODO change image resource. this operation will be deleted later. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.big_droid); imageView.setImageBitmap(bitmap); return contentView; }
オプションメニューを選択した時の設定
=============================================
選択した画像をシェアする
- create method
- void shareCurrentPhoto()
- create AsyncTask that inner class into the shareCurrentPhoto method.
- change onActionItemClicked method
- call of share proccess.
ContentFragment.java
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
package com.hidecheck.honeycomic; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.app.ActionBar; import android.app.Activity; import android.app.Fragment; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.View.OnSystemUiVisibilityChangeListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.Toast; public class ContentFragment extends Fragment { private View contentView; // The bitmap currently used by ImageView private Bitmap bitmap = null; // Current action mode (contextual action bar, a.k.a. CAB) private ActionMode currentActionMode; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { contentView = inflater.inflate(R.layout.content_wellcome, null); final ImageView imageView = (ImageView)contentView.findViewById(R.id.image); contentView.setDrawingCacheEnabled(false); // TODO setting DragListener later // Keep the action bar visibility in sync with the system status bar. That is, when entering // 'lights out mode,' hide the action bar, and when exiting this mode, show the action bar. final Activity activity = getActivity(); contentView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { ActionBar actionBar = activity.getActionBar(); if(actionBar != null){ contentView.setSystemUiVisibility(visibility); if(visibility == View.STATUS_BAR_VISIBLE){ actionBar.show(); }else{ actionBar.hide(); } } } }); contentView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(contentView.getSystemUiVisibility() == View.STATUS_BAR_VISIBLE){ contentView.setSystemUiVisibility(View.STATUS_BAR_HIDDEN); }else{ contentView.setSystemUiVisibility(View.STATUS_BAR_VISIBLE); } } }); // When long-pressing a photo, activate the action mode for selection, showing the // contextual action bar (CAB). contentView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { if(currentActionMode != null){ return false; } currentActionMode = getActivity().startActionMode(contentSelectionActionCallback); contentView.setSelected(true); return true; } }); // TODO change image resource. this operation will be deleted later. bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.big_droid); imageView.setImageBitmap(bitmap); return contentView; } void shareCurrentPhoto() { File externalCacheDir = getActivity().getExternalCacheDir(); if(externalCacheDir == null){ Toast.makeText(getActivity(), "Error writing to USB/external storage.", Toast.LENGTH_SHORT).show(); return; } // Prevent media scanning of the cache directory. final File noMediaFile = new File(externalCacheDir, ".nomedia"); try{ noMediaFile.createNewFile(); }catch (IOException e) { Log.e(getClass().getName(), "shareCurrentPhoto", e); } // Write the bitmap to temporary storage in the external storage directory (e.g. SD card). // We perform the actual disk write operations on a separate thread using the // {@link AsyncTask} class, thus avoiding the possibility of stalling the main (UI) thread. final File tempFile = new File(externalCacheDir, "tempfile.jpg"); new AsyncTask<Void, Void, Boolean>(){ /** * Compress and write the bitmap to disk on a separate thread. * @return TRUE if the write was successful, FALSE otherwise. */ @Override protected Boolean doInBackground(Void... params) { try{ FileOutputStream fo = new FileOutputStream(tempFile, false); if(!bitmap.compress(Bitmap.CompressFormat.JPEG, 60, fo)){ Toast.makeText(getActivity(), "Error writing bitmap data.", Toast.LENGTH_SHORT).show(); return Boolean.FALSE; } return Boolean.TRUE; }catch (FileNotFoundException e) { Toast.makeText(getActivity(), "Error writing to USB/external storage.", Toast.LENGTH_SHORT).show(); return Boolean.FALSE; } } /** * After doInBackground completes (either successfully or in failure), we invoke an * intent to share the photo. This code is run on the main (UI) thread. */ @Override protected void onPostExecute(Boolean result) { if(result != Boolean.TRUE){ return; } Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile)); shareIntent.setType("image/jpeg"); startActivity(Intent.createChooser(shareIntent, "Share photo")); } }.execute(); } private ActionMode.Callback contentSelectionActionCallback = new ActionMode.Callback() { @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { contentView.setSelected(false); currentActionMode = null; } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.setTitle(R.string.photo_selection_cab_title); MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.photo_context_menu, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.share: shareCurrentPhoto(); mode.finish(); return true; } return false; } }; }
AndroidManifest.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
sdcardの書き込みを有効にする
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>