アプリ作って海外移住

コピペプログラマーのメモ

動画 表示 サムナイル取得

 

動画表示

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);

 

 

bmp使った後はbmp=null してメモリ削減

 

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が必要。

 

画面内容、スクロール位置の復元は自分でやれという事だ。