動画 表示 サムナイル取得
動画表示
String path ="/storage/sdcard1/DCIM/Camera/VID_20160229_225732.3gp";
final VideoView vv1 = (VideoView)findViewById(R.id.vv1);
vv1.setVideoPath(path);
vv1.start();
// 再生完了通知リスナー
vv1.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// 先頭に戻す -> Repeat
vv1.seekTo(0);
// 再生開始
vv1.start();
}
});
サムネイル
ImageView iv3 = (ImageView)findViewById(R.id.iv3);
String path ="/storage/sdcard1/DCIM/Camera/VID_20160229_225732.3gp";
Bitmap bmThumbnail;
bmThumbnail = ThumbnailUtils.createVideoThumbnail(
path,
MediaStore.Video.Thumbnails.MINI_KIND);
iv3.setImageBitmap( bmThumbnail);
Fragment BackKey の制御
////////////////////backkey listenner
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// onKey 2回呼ばれるのでフィルターが必要
//the first time for key down, and the second time for key up,
if (event.getAction()!=KeyEvent.ACTION_DOWN) return false;
if(keyCode == KeyEvent.KEYCODE_BACK){
finishDialog();
return true;
}
return false;
}
});
//フォーカスをあてる。
view.setFocusableInTouchMode(true);
view.requestFocus();
addでfragmentを重ねる場合、次のfragmentにもフォーカスをあてないと
このバックキーが動くので注意
---------------------------------以下 よくわからないので 無しにする。
transaction.addToBackStack(null); でバックキーの制御できるが、
終了するとき、例えば、
OyaFragmentでバックキー押して、ダイアログで確認メッセージ表示したい場合
OyaFragmentだけ、
iew.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN)
finishDialog();
Log.w(TAG,"on pressed back key");
return false;
}
});
view.setFocusableInTouchMode(true);
view.requestFocus();
でバックキー処理したいけど、view.requestFocus();しないといけない。
これが、子fragment で解除できるけど、子からバックキーで戻った時、onresume も実行されないので、再度view.requestFocus();できない。
そこで、バックキーはすべて、MainActivityで制御。
ただし、transaction.addToBackStack(null); で普通にFragment画面遷移すること。
あとで、BackStackの中身をチェックするから、
まず、MainActivityで、onBackPressed()作成
これで、バックキーイベントはここに集まる。
findFragmentByTagでFragment取得
Fragment nowFragment = fragmentManager.findFragmentById(R.id.f1);
で、今表示中のFragment取得。
FragmentManager.popBackStack();は、普通通りバックキーで戻りなさいの命令。
これで、特定のFragmentのバックキー制御ができる。
あいかわらず、Fragmentに悩まされる。
@Override
public void onBackPressed(){
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment oyaF= fragmentManager.findFragmentByTag("oya");
Fragment koF= fragmentManager.findFragmentByTag("ko");
Fragment inputF= fragmentManager.findFragmentByTag("inputtext");
Fragment nowFragment = fragmentManager.findFragmentById(R.id.f1);
if(nowFragment ==oyaF){
Toast.makeText(MainActivity.this, "oya bkkeyがクリックされました", Toast.LENGTH_SHORT).show();
finishDialog();
}else if(nowFragment ==koF){
Toast.makeText(MainActivity.this, "ko bkkeyがクリックされました", Toast.LENGTH_SHORT).show();
fragmentManager.popBackStack();
}else if(nowFragment == inputF){
fragmentManager.popBackStack();
}
}
private void finishDialog() {
// OkCancelDialog dialogFragment = OkCancelDialog
// .newInstance("自分メモ", "終了します");
OkCancelDialog dialogFragment = OkCancelDialog.newInstance("自分メモ", "終了します");
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
// transaction.replace(R.id.f1, oyaFragment, "oya");
transaction.add(dialogFragment, "dialog");
//transaction.addToBackStack(null);
transaction.commit();//AllowingStateLoss();
dialogFragment.setOnOkClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Toast.makeText(MainActivity.this, "OKがクリックされました", Toast.LENGTH_SHORT).show();
finish();
//listener.onFinish();//addkey 表示finish();
}
});
dialogFragment.setOnCancelClickListener(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Toast.makeText(MainActivity.this, "Cancelがクリックされました", Toast.LENGTH_SHORT).show();
}
});
}
Fragment バックキーリスナー
////////////////////backkey listenner
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN)
listener.onFinush();
Log.w(TAG,"on pressed back key");
return false;
}
});
view.setFocusableInTouchMode(true);
view.requestFocus();
view.requestFocus();でフォーカスを当てないとだめ!
interface
子Fragment側(イベント発生側)
まず、イベントlistener を作る。
private addKeyListener listener = null;
public interface addKeyListener {
void onAddKeyVISIBLE();
void onAddKeyINVISIBLE();
}
listener定義
//MainActivity callingActivity = (MainActivity) getActivity();
listener = (addKeyListener) getActivity();//callingActivity;
イベントが発生したら、listenerに伝える。
listener.onAddKeyVISIBLE();//addkey 表示
親MainActivity側
まず、implementsする。
public class MainActivity extends AppCompatActivity
implements
OyaFragment.addKeyListener {
メソッド作成しろと言われるのでその通りにする。
メソッドにやりたい事を書く。
@Override
public void onAddKeyVISIBLE() {
LinearLayout linearAdd = (LinearLayout)findViewById(R.id.linearAdd);
// linearAdd.setVisibility(View.VISIBLE);
}
@Override
public void onAddKeyINVISIBLE() {
LinearLayout linearAdd = (LinearLayout)findViewById(R.id.linearAdd);
// linearAdd.setVisibility(View.INVISIBLE);
}
以上で完成。
たったこれだけなのに、難しかった!
クリックだけじゃなく、フラグONなど、多様性抜群
Fragment いろいろ 終了 データ受け渡し
---1---
Fragmentの終了 finish() の事。
getFragmentManager().beginTransaction().remove(this).commit();//BackStackなし
getFragmentManager().popBackStack();//BackStackあり
---2---
Activity==> Fragment
Bundleを使う
koFragment = new KoFragment();
Bundle bundle = new Bundle();
bundle.putInt("oyaId", oyaId);
koFragment.setArguments(bundle);// フラグメントに渡す値をセット
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.f1, koFragment,"ko");
transaction.addToBackStack(null);
transaction.commit();
---3---
Fragment==> Activityのデータ受け渡し
Activity 内の public void onReturn_KoCall(int oyaId) を呼んでデータを渡す。
MainActivity callingActivity = (MainActivity) getActivity();
callingActivity.onReturn_KoCall(oyaId);////
---4---
Fragment 親 ==> Fragment 子 のデータ受け渡し
これ理解するの大変だった。なんかnewInstanceはjavaの常識を覆す手法だ
-------setTargetfragment(this)が使えなかったので以下の手法をとる。
親側
まず、 newInstanceでデータ受け渡し
その時にthisFragment を取得しておく。
あとで、子 Fragment を呼ぶときに setTargetfragment するときに必要
thisFragmentは、
Fragment inputF= fragmentManager.findFragmentByTag("inputtext");
Fragment nowFragment = fragmentManager.findFragmentById(R.id.f1);
でも取得できる。
private String scrollPos;
private static Fragment thisFragment;
//Fragment お決まりのパターン
// メモリ不足による破棄後からの復帰時にフレームワークがリフレクションで呼びだすコンストラクタ
public OyaFragment() {}
//newInstance データ受け取り Bundleで必ずセット
public static OyaFragment newInstance(String scrollPos) {
OyaFragment f = new OyaFragment();
// 引数を設定
Bundle args = new Bundle();
args.putString("scrollPos", scrollPos);
f.setArguments(args);
thisFragment = f;
return f;
}
次に、子 Fragment を呼ぶ
thisFragment,requestCode,と一緒に各引数をセットして newInstanceを呼ぶ
InputTextFragment inputTextFragment;
String defortText = "無題のメモ帳";
String dialogTitle= "新しいメモ帳を作成します。";
String dialogMsg = "後で変更する事もできます。";
String fromCall = "NewAddFromOya";
inputTextFragment = InputTextFragment.newInstance(thisFragment,requestCode,
defortText,dialogTitle,dialogMsg,fromCall,oyaId);
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//transaction.replace(R.id.f1, inputTextFragment, "inputtext");
transaction.add(R.id.f1, inputTextFragment, "inputtext");
// inputTextFragment.setTargetFragment(MainActivity.getOyaFragment(), 37);
transaction.addToBackStack(null);
transaction.commit();
子側
まず、 newInstanceでデータ受け渡し 親と一緒
違うのは、f.setTargetFragment(fragment, requestCode);で親Fragment とrequestCode をsetTargetFragmentする。
この親Fragmentが、さっき親で取得したthisFragmentなのです。
private int requestCode;
private Fragment target;
private Fragment thisFragment;
// メモリ不足による破棄後からの復帰時にフレームワークがリフレクションで呼びだすコンストラクタ
public InputTextFragment() {}
//newInstance データ受け取り Bundleで必ずセット
public static InputTextFragment newInstance(
Fragment fragment, int requestCode, String defortText, String dialogTitle, String dialogMsg, String fromCall, int oyaId) {
InputTextFragment f = new InputTextFragment();
f.setTargetFragment(fragment, requestCode);
// 引数を設定
Bundle bundle = new Bundle();
bundle.putString("defortText", defortText);
bundle.putString("dialogTitle", dialogTitle);
bundle.putString("dialogMsg", dialogMsg);
bundle.putString("fromCall", fromCall);
bundle.putInt("oyaId", oyaId);
f.setArguments(bundle);
//ragment = f;
//target = fragment;
return f;
}
そしてcreateview などでデータ取得する。targetがさっき親で取得したthisFragment。
target = getTargetFragment();
requestCode = getTargetRequestCode();
Bundle bundle = getArguments();
//String name = bundle.getString("Name");
String defortText = bundle.getString("defortText");
String dialogTitle = bundle.getString("dialogTitle");
String dialogMsg = bundle.getString("dialogMsg");
fromCall = bundle.getString("fromCall");
oyaId= bundle.getInt("oyaId");
さらに、
結果を親に渡す。
wwwを戻す場合、親Fragment の onActivityResult requestcode 37 で受け取る。
Intent result = new Intent();
result.putExtra("www", www);
target.onActivityResult(37, Activity.RESULT_OK, result);
// getFragmentManager().beginTransaction().remove(this).commit();//BackStackなし
getFragmentManager().popBackStack();//BackStackあり
Fragment 間 Arraylistのデータ受け渡し
親側
Bundle bundle = new Bundle();
bundle.putStringArrayList("results", results);
bundle.putString("aaa", results.get(0));
newFragment.setArguments(bundle);// フラグメントに渡す値をセット
newFragment.setTargetFragment(null, 202);
newFragment.show(getActivity().getFragmentManager(), "dialog");
受け取り側
resultsはarraylist
private ArrayList<String> results = new ArrayList<String>();
.......
Bundle bundle = getArguments();
String aaa = bundle.getString("aaa");
results = getArguments().getStringArrayList("results");
スクロール位置の復元 Fragment 画面遷移で戻った時、スクロール位置を復元したい。
これは必要なし!
クリックでFragment 画面遷移の場合
Click => onDestroyView() => 呼ばれるFragment実行
戻った時、onCreateView onResume が呼ばれる。
onCreateが呼ばれない。ここがミソ。
スクロール位置復元はSaveInstanceState を使わなくても。
クリック時にスクロール位置を取得しておけばよい。
mScrollY = mScrollView.getScrollY();
で、Resumeで scrollTo してあげる。
mScrollView =(ScrollView)getActivity().findViewById(R.id.scrollView);
mScrollView.post(new Runnable(){
public void run()
{ //mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
// mScrollView.scrollTo(0,mScrollY);
}
});
onCreateが呼ばれないので、mScrollYは保持してる。
mScrollView.post(new Runnable(){ してあげないと scrollTo しない。
理由は不明。
**************Intentの場合*******************
Androidは機種メーカーによって、ライフサイクルが違う場合がある。
画面遷移から戻った時、Listview RecyclerView ScrollView など、元の状態に戻らない機種がある。
Intent して戻った時、onCreate を実行しない機種はOK
onCreate を実行する機種は上記のような処理が必要。SaveInstanceStateが必要。
画面内容、スクロール位置の復元は自分でやれという事だ。