Share
Embed
ビンゴアプリハンズオン / Bingo hands-on
Android Bazaar and Conference 2019 Spring
https://abc.android-group.jp/2019s/
Yuki Anzai
May 26, 2019
Transcript
51 slides
-
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 -
My Bingo Finish をクリック com.sample.mybingo デフォルトのままでOK API 21: Android 5.0
Java Use androidx.* artifact にチェック -
text の Hello World! を削除 プレビュー⽤の text に 1, 2,
3, 4, 5 と⼊⼒ -
1. text の右端の⼩さい ボタンをクリック 2. Add new resources, New string
Value... をクリック -
上のハンドルを drag して 上部の TextView の ハンドルにつなげる 下のハンドルを drag して
下部の Button の ハンドルにつなげる -
<?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> -
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); } } -
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()); } }); } -
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); } }); -
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()); } }); } -
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(); } } -
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); -
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); } } -
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 -
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; } -
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(); } } -
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); -
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); } } }); } -
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; } -
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(); } -
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; } } } -
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); } } }); -
public class MainActivity extends AppCompatActivity { ... @Override protected void
onCreate(Bundle savedInstanceState) { ... button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { viewModel.pickNextNumber(); } }); } }