読者です 読者をやめる 読者になる 読者になる

最近ハマった事象の備忘録(SupporLibrary編2)

はじめに

前回のまとめは

最近ハマった事象の備忘録(SupporLibrary編) - exception think

古いアプリをマテリアルデザイン化に簡単にしようとすると

  • SnackBarを使う
  • AppCompatXXX 系の部品を使う
    • AppCompatSpinner とか
  • BottomSheetDialogを使う

あたりになるわけですが、ココらへんに関してハマった話をメモしておこうかと

SnackBar編

SnackBarの表示初期化中にBackKeyで戻ったりするとアプリが落ちる

Toastの代わりにSnackBarを使いましょう みたいなお話がじつはあったりしますが

これSnackBarの表示初期化中にBackKeyで戻ったりするとアプリが落ちます*1

シーケンシャルスレッド処理ではないからでしょうね・・

public void infoBar(int resID){
    infoBar(getString(resId));
}

public void infoBar(String msg){
    View parent = findViewById(R.id.actionBar);
    if(parent == null){
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }
    else{
        Snackbar snackbar = Snackbar.make(parent, msg, Snackbar.LENGTH_LONG);
        snackbar.show();
    }
}

な感じでコンパチにしておくのがベターかな~

同じような話で

data-binding で下記のようなコードが合ったりしますが

これも表示中にキャンセルすると、executePendingBindings で落ちるので

try-catchしておくのがよいかと。避けようがないので・・

  • NG
@Override
    public void onBindViewHolder(ItemViewHolder holder, int position) {
        User user = mUserList.get(position);

        // Userデータをセット。BR.userはxmlのvariableの名前
        holder.getBinding().setVariable(BR.user, user);
        holder.getBinding().executePendingBindings();
    }
@Override
    public void onBindViewHolder(ItemViewHolder holder, int position) {
        User user = mUserList.get(position);

        // Userデータをセット。BR.userはxmlのvariableの名前
        holder.getBinding().setVariable(BR.user, user);
        try{
            holder.getBinding().executePendingBindings();
        }catch(Exception ex){
        }
    }

SnackBarの文字が黒字でみえないことが有る

AppCompatのstyle.xmlが新し目のものは整備されているのですが、

4系とかそれ以前のものだとstyle.xml がデフォルトでちゃんと用意されていないので、背景が黒、文字も黒で見えない みたいな話になります

前回の話の AlertDialogと同じ話ですね。。

SnackBar自体の色は基本 黒のようなので、文字色だけ明示的に指定するようにします

Snackbar snackbar = Snackbar.make(view, msg, Snackbar.LENGTH_LONG);
View view = snackbar.getView();
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
tv.setTextColor(Color.WHITE);
snackbar.show();

参考

AppCompatSpinnerの選択状態

android:entriesを設定している場合、

selection処理とentries初期化処置がかち合ってしまうのでDelayかける必要が有り

 <android.support.v7.widget.AppCompatSpinner
        android:entries="@array/list_items"
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
  • NG
AppCompatSpinner spinner = (AppCompatSpinner) findViewById(R.id.spinner);
spinner.setSelection(0);
final AppCompatSpinner spinner = (AppCompatSpinner) findViewById(R.id.spinner);

spinner.postDelayed(new Runnable() {
    @Override
     public void run() {
        spinner.setSelection(0);
    }
});
 

BottomSheetDialogについて

BottomSheetDialog mBottomSheetDialog = new BottomSheetDialog(getActivity());

View view = XXX; //★

mBottomSheetDialog.setContentView(view);
mBottomSheetDialog.show();

★の部分はよく RecyclerViewのサンプルがググるとでてきますが、

単なるViewですので、もちろんListViewでもOK

ただもちろん

  • バックグラウンド背景が黒透明になるのを透明にできない
    • Dialogなので仕方ない
  • FloatingActionButtonと連動できない
    • CoordinatorLayout + BottomSheetBehavior を使うことは出来ない
    • 其の場合は、layout上に BottomSheetにしたいViewに属性を追加する

下記のようにレイアウトべた書きになる事を、企画デザインの方に説明しておかないと

結構勘違いされることになります。。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/coordinator_layout"
    tools:context=".MainActivity"
    >


  <!--BottomSheetで使いたいレイアウト -->
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      app:layout_behavior="@string/bottom_sheet_behavior" //★
      app:behavior_peekHeight="200dp"                                  //★
      android:background="@android:color/white">

  </LinearLayout>
  
  <!--CoordinatorLayoutと連動するFabボタン -->
   <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_add_white_24dp"
        design:fabSize="normal"
        design:layout_anchor="@id/coordinator_layout" //★
        design:layout_anchorGravity="bottom|right"       //★
        />
</android.support.design.widget.CoordinatorLayout>

BottomSheetBehavior自体は、BottomSheetDialogでも使えるんですけどね。。

dialog.setContentView(view);
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
mBehavior.setPeekHeight(300);//表示初期高さサイズ
dialog.show();

*1:parentのViewが参照エラーで