2018年6月20日水曜日

LiveData を UnitTest でテストする

デザートの文字列を保持して、追加・削除されたタイミングで保持数を LiveData で通知する DessertsHolder を UnitTest でテストしてみましょう。 class DessertsHolder { private val counter = MutableLiveData<Int>() private val list = mutableListOf<String>() init { counter.value = 0 } fun getCounter(): LiveData<Int> = counter fun add(item: String) { list.add(item) counter.value = list.size } fun remove(item: String) { list.remove(item) counter.value = list.size } fun clear() { list.clear() counter.value = 0 } } 特に何もせず次のような普通の UnitTest を書くと、Looper が mock されていないというエラー(RuntimeException: Method getMainLooper in android.os.Looper not mocked. )がでます。 class DessertsHolderTest { @Test fun test() { val holder = DessertsHolder() holder.add("Donuts") assertThat(holder.getCounter().value).isEqualTo(1) } }

そこで、まず AAC の core-testing ライブラリを追加します。 dependencies { def lifecycle_version = "1.1.1" testImplementation "android.arch.core:core-testing:$lifecycle_version" }
そして @get:Rule で rule に InstantTaskExecutorRule を指定します。このとき get: をつけないと rule が public ではないという ValidationError (ValidationError: The @Rule 'rule' must be public.)が起こるので注意しましょう。 class DessertsHolderTest { @get:Rule val rule: TestRule = InstantTaskExecutorRule() @Test fun test() { ... } }


2018年6月9日土曜日

ViewOutlineProvider を使う

API Level 21 に追加された ViewOutlineProvider では shadow casting と outline clipping に利用する Outline を指定できます。

ViewOutlineProvider の getOutline() の引数で渡される Outline に Rect, RoundRect, Oval または ConvexPath を指定します。

View が持つ Drawable が invalidate されたり、View のサイズが変わったり、View の invalidateOutline() が呼ばれると getOutline() が呼ばれます。 private val clipOutlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { val margin = min(view.width, view.height) / 10 outline.setOval( 0, 0, view.width, view.height ) } } View の setOutlineProvider() で ViewOutlineProvider を指定します。outline clipping を有効にするには setClipToOutline() で true を指定します。

outline clipping は現状 RoundRect か Circle(Oval で縦横のサイズが同じ)のときだけ効きます。
clip しても View のサイズには影響しないためクリック領域などはそのままです。 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) clippedView.outlineProvider = clipOutlineProvider clippedView.clipToOutline = true } 左 : clipToOutline = false, 右 : clipToOutline = true





2018年6月7日木曜日

ConstraintLayout で float で指定する属性

ConstraintLayout 1.1.0 の属性のうち、TypedArray から getFloat() で取得されている属性は
  • app:layout_constraintCircleAngle
  • app:layout_constraintGuide_percent
  • app:layout_constraintHorizontal_bias
  • app:layout_constraintVertical_bias
  • app:layout_constraintHeight_percent
  • app:layout_constraintWidth_percent
  • app:layout_constraintHorizontal_weight
  • app:layout_constraintVertical_weight
です。

これらの属性は app:layout_constraintGuide_percent="0.3" のように値を直接指定するときは float 形式で書きます。

float 値を resource で定義するには、 <?xml version="1.0" encoding="utf-8"?> <resources> <item name="guideline_percent" type="dimen" format="float">0.3</item> </resources> のように item タグ を使って float format、dimen type で定義します。 app:layout_constraintGuide_percent="@dimen/guideline_percent"