Hatena::ブログ(Diary)

前人未踏の領域へ

2017-11-16

[]ConstraintLayoutでsetVisibilityが反映されないケース


constraint.Groupに含まれるViewは単独でView.GONEを割り当てても反映されないらしい。
バグか仕様かは不明。

2017-10-24

[]テキストのStyleを動的に変更する


課題

値が設定済みだったらdisabledになるようにテキストのスタイルを変更したい

対応

Styleの動的な変更は結構面倒なのだが、android:textAppearanceなど、スタイルを引数に取るタイプの
属性についてはそのメソッドが使うことでスタイルの変更が簡単にできる。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    holder.label?.setTextAppearance(R.style.text_disabled)
} else {
    holder.label?.setTextAppearance(context, R.style.text_disabled)
}

2017-10-23

[]Radioボタンリスト型のAlertDialogを作る


要件

AlertDialogから選択をさせたい。その際の選択肢をRadioButtonで表示したいが
どうすればよいか。また、リストを選択した時点ではダイアログを閉じないようにしたい。

対応


  • ViewをRadioButtonで作る
  • Adapterを独自に定義、設定する
  • RadioボタンのクリックイベントをOFFにする
  • Radioボタンのチェックを自前でON/OFFする

ViewをRadioButtonで作る

RadioButton付きのリストは自分で用意する。RadioButtonはTextViewを継承しているので
ArrayAdapterにそのまま渡すことができる。

<!-- layout/list_item_radio_text.xml -->
<android.support.constraint.ConstraintLayout 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="?android:attr/listPreferredItemHeightSmall">

    <RadioButton
        android:id="@+id/radio_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="サンプルテキスト" />
</android.support.constraint.ConstraintLayout>


Adapterをセットする

通常はsetAdapterでも良いはずだが、その場合はアイテムを選択した時点でDialogがdismissされる。
これを回避するためにsetSingleChoiceItemsにadapterを渡す

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

    val sampleArray = context.resources.getStringArray(R.array.sample_array) //一覧で使うString配列
    val adapter = ArrayAdapter<String>(context, R.layout.list_item_radio_text, R.id.radio_text, sampleArray)

    val builder = AlertDialog.Builder(activity)
        builder.setSingleChoiceItems(adapter, -1, { dialog, which ->
                   
                })

RadioボタンのクリックイベントをOFFにする

ListViewのアイテムクリックイベントはRadioButtonのチェックイベントに横取りされてしまうため、
イベントが発動しないように細工をする必要がある。

    <RadioButton
        android:focusable="false"
        android:visibility="visible" />

Radioボタンのチェックを自前でON/OFFする

クリックイベントをOFFにしたため、ListViewのonItemClickは呼ばれるようになったが
今度はRadioのチェックのON/OFFを自分で書かないといけない。

class RadioTextListDialog : DialogFragment() {

    var tmpRadio: RadioButton? = null

 val builder = AlertDialog.Builder(activity)
        builder.setSingleChoiceItems(adapter, -1, { dialog, which ->
                    val d = dialog as AlertDialog
                    val v = d.listView.getChildAt(which)
                    val radio = v.findViewById<RadioButton>(R.id.radio_text)
                    radio.isChecked = true
                    //選択されていたものをOFF
                    if (tmpRadio != radio) {
                        tmpRadio?.isChecked = false
                        tmpRadio = radio
                    }
                })


PreferenceFragmentが使えそうだったらそちらを推奨

2017-10-19

[]RecyclerViewのaddItemDecorationについて


RecyclerViewに対して行間に区切り線(divider)をつけるときにaddItemDecoration()というメソッドを使用する。
このメソッドは2つあり、
addItemDecoration(ItemDecoration decor, int index) と
addItemDecoration(ItemDecoration decor) である。

てっきりindexで行番号を指定してその行だけ任意のdividerをつけられるのかと思ったがそうではなかった。
実際にはdecorationの描画順を表しているらしく、全ての行に対して設定したdecerationが全て適用された
状態で表示される。

とはいえ色の上書きが記述順に関係している様子もないのでこの辺は謎である。

[]Layoutにstate_pressedを認識させる

課題

ConstraintLayoutにタッチフィードバックをつけたい。selectorのstate_pressedを使おうとしたが
反応しない。どうすればよいか。

対応


selectorのstate_pressedはViewがclickableでないと反応しない。

<android.support.constraint.ConstraintLayout
    android:clickable="true"
    android:focusable="true"
    android:background="?android:attr/selectableItemBackground"
>

android:focusable=trueでないとclickもできないので合わせて設定。ないと警告がでる。
?android:attr/selectableItemBackgroundを使えば自分で作らなくてもエフェクトしてくれる

参考

https://stackoverflow.com/questions/21273510/android-linearlayout-selector-background-color

2017-10-16

[]マージン付きのdivider用drawableを作る


お題


RecyclerViewで使用するdividerの左側にマージンを確保したい。

対応

レイヤーリストとoffsetの組み合わせでできた。

とりあえず基本となるdividerを用意する(drawable/divider.xml などとする)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="1dp"
        android:height="1dp" />
    <solid android:color="@color/divider" />
</shape>

これをレイヤーリストの中にいれ、オフセットを確保する今回は72dp。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:left="72dp">
        <shape android:shape="rectangle">
            <size
                android:width="1dp"
                android:height="1dp" />
            <solid android:color="@color/divider" />
        </shape>
    </item>
</layer-list>

こいつをDividerItemDecorationにsetDrawableする

        val decoration = DividerItemDecoration(context, layoutManager.orientation)
        decoration.setDrawable(ContextCompat.getDrawable(context, R.drawable.divider))
        mListView.addItemDecoration(decoration)

これで上下左右任意にマージンを確保できそう