Bingo hands-on

Bingo hands-on

D2bcabeeb1ddff142fb8988b412cb4d3?s=128

Yuki Anzai

May 26, 2019
Tweet

Transcript

  1. ビンゴアプリハンズオン あんざいゆき(@yanzm) ABC 2019S

  2. Yuki Anzai • Android App Developer (2009~) • CEO of

    uPhyca Inc. (2011~) • Google Developer Expert for Android • Organizer of GTUG Girls and droid girls • Twitter : @yanzm
  3. クリック

  4. 1.クリック 2. Next を クリック

  5. My Bingo Finish をクリック com.sample.mybingo デフォルトのままでOK API 21: Android 5.0

    Java Use androidx.* artifact にチェック
  6. None
  7. 1.ダブルクリック 2. Design をクリック

  8. Blueprint を選択

  9. クリック

  10. 0dp (match_constraint) に変更 bottom のハンドルをクリック

  11. None
  12. 左右と上の margin を 16 に変更

  13. text の Hello World! を削除 プレビュー⽤の text に 1, 2,

    3, 4, 5 と⼊⼒
  14. id を historyView に変更

  15. Palette から Button を drag して下部に drop

  16. Infer Constrains をクリック

  17. layout_width を 0dp (match_contstrains) にし、margin を変更

  18. 1. text の右端の⼩さい ボタンをクリック 2. Add new resources, New string

    Value... をクリック
  19. next_number 次の数字を出す OK をクリック

  20. None
  21. Palette から TextView を drag して真ん中あたりに drop

  22. 上のハンドルを drag して 上部の TextView の ハンドルにつなげる 下のハンドルを drag して

    下部の Button の ハンドルにつなげる
  23. Infer Constrains をクリック

  24. layout_width と layout_height を 0dp (match_contstrains) にし、margin を変更

  25. クリックして展開

  26. gravity を展開して center を true に変更

  27. textSize を 100sp に変更 text を削除してプレビュー の text を 75

    に変更
  28. id を numberView に変更

  29. design にして⾒た⽬を 確認

  30. <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.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="match_parent" tools:context=".MainActivity">

    <TextView android:id="@+id/historyView" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" android:layout_marginRight="16dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" tools:text="1, 2, 3, 4, 5" /> <Button android:id="@+id/button" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:text="@string/next_number" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/numberView" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:gravity="center" android:textSize="100sp" app:layout_constraintBottom_toTopOf="@+id/button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/historyView" tools:text="75" /> </androidx.constraintlayout.widget.ConstraintLayout>
  31. ダブルクリック

  32. public class MainActivity extends AppCompatActivity { private TextView historyView; private

    TextView numberView; private View button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); historyView = findViewById(R.id.historyView); numberView = findViewById(R.id.numberView); button = findViewById(R.id.button); } }
  33. public class MainActivity extends AppCompatActivity { private TextView historyView; private

    TextView numberView; private View button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); historyView = findViewById(R.id.historyView); numberView = findViewById(R.id.numberView); button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { numberView.setText("" + System.currentTimeMillis()); } }); }
  34. public class MainActivity extends AppCompatActivity { private TextView historyView; private

    TextView numberView; private View button; private final Random random = new Random(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int nextNumber = random.nextInt(75) + 1; numberView.setText("" + nextNumber); } });
  35. public class MainActivity extends AppCompatActivity { ... private final List<Integer>

    histories = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int nextNumber = random.nextInt(75); numberView.setText("" + nextNumber); histories.add(nextNumber); historyView.setText(createHistoryText()); } }); }
  36. public class MainActivity extends AppCompatActivity { ... private String createHistoryText()

    { final StringBuilder sb = new StringBuilder(); boolean isFirst = true; for (int history : histories) { if (isFirst) { isFirst = false; } else { sb.append(", "); } sb.append(history); } return sb.toString(); } }
  37. public class MainActivity extends AppCompatActivity { ... private final List<Integer>

    pickNumbers = new ArrayList<>(); private final List<Integer> histories = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pickNumbers.clear(); for (int i = 1; i <= 75; i++) { pickNumbers.add(i); } historyView = findViewById(R.id.historyView); numberView = findViewById(R.id.numberView); button = findViewById(R.id.button);
  38. public class MainActivity extends AppCompatActivity { ... @Override protected void

    onCreate(Bundle savedInstanceState) { ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int index = random.nextInt(pickNumbers.size()); final int nextNumber = pickNumbers.remove(index); numberView.setText("" + nextNumber); histories.add(nextNumber); historyView.setText(createHistoryText()); if (pickNumbers.isEmpty()) { button.setEnabled(false); } }
  39. チャレンジ課題

  40. ViewModel を使う

  41. https://developer.android.com/jetpack/androidx/releases/lifecycle dependencies { ... def lifecycle_version = "2.0.0" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" } build.gradle (Module: app) Android developer ページ → Jetpack → AndroidX → Release Notes → androidx.lifecycle
  42. public class MainViewModel extends ViewModel { private final Random random

    = new Random(); private final List<Integer> pickNumbers = new ArrayList<>(); private final List<Integer> histories = new ArrayList<>(); public MainViewModel() { for (int i = 1; i <= 75; i++) { pickNumbers.add(i); } } int pickNextNumber() { final int index = random.nextInt(pickNumbers.size()); final int nextNumber = pickNumbers.remove(index); histories.add(nextNumber); return nextNumber; }
  43. String createHistoryText() { final StringBuilder sb = new StringBuilder(); boolean

    isFirst = true; for (int history : histories) { if (isFirst) { isFirst = false; } else { sb.append(", "); } sb.append(history); } return sb.toString(); } boolean isAllPicked() { return pickNumbers.isEmpty(); } }
  44. public class MainActivity extends AppCompatActivity { private TextView historyView; private

    TextView numberView; private View button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); historyView = findViewById(R.id.historyView); numberView = findViewById(R.id.numberView); button = findViewById(R.id.button); final MainViewModel viewModel = ViewModelProviders.of(this) .get(MainViewModel.class);
  45. public class MainActivity extends AppCompatActivity { ... @Override protected void

    onCreate(Bundle savedInstanceState) { ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final int nextNumber = viewModel.pickNextNumber(); numberView.setText("" + nextNumber); historyView.setText(viewModel.createHistoryText()); if (viewModel.isAllPicked()) { button.setEnabled(false); } } }); }
  46. LiveData を使う

  47. public class MainViewModel extends ViewModel { private final Random random

    = new Random(); private final List<Integer> pickNumbers = new ArrayList<>(); private final List<Integer> histories = new ArrayList<>(); private final MutableLiveData<State> state = new MutableLiveData<>(); public MainViewModel() { pickNumbers.clear(); for (int i = 1; i <= 75; i++) { pickNumbers.add(i); } } LiveData<State> getState() { return state; }
  48. void pickNextNumber() { final int index = random.nextInt(pickNumbers.size()); final int

    nextNumber = pickNumbers.remove(index); histories.add(nextNumber); state.setValue(new State(nextNumber, createHistoryText(), isAllPicked())) } private String createHistoryText() { final StringBuilder sb = new StringBuilder(); boolean isFirst = true; for (int history : histories) { if (isFirst) { isFirst = false; } else { sb.append(", "); } sb.append(history); } return sb.toString(); }
  49. private boolean isAllPicked() { return pickNumbers.isEmpty(); } static class State

    { final int nextNumber; final String historyText; final boolean isAllPicked; State(int nextNumber, String historyText, boolean isAllPicked) { this.nextNumber = nextNumber; this.historyText = historyText; this.isAllPicked = isAllPicked; } } }
  50. public class MainActivity extends AppCompatActivity { ... @Override protected void

    onCreate(Bundle savedInstanceState) { ... viewModel.getState().observe(this, new Observer<MainViewModel.State>() { @Override public void onChanged(MainViewModel.State state) { numberView.setText("" + state.nextNumber); historyView.setText(state.historyText); if (state.isAllPicked) { button.setEnabled(false); } } });
  51. public class MainActivity extends AppCompatActivity { ... @Override protected void

    onCreate(Bundle savedInstanceState) { ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { viewModel.pickNextNumber(); } }); } }