Membangun Aplikasi Android Dadu Produk Minimum yang layak menggunakan konstruksi Android dasar.

Vector AndroidRelativeLayout , ConstraintLayout , LinearLayout ]ListView dan ArrayAdapter ListView dan Logika AdapterBeberapa saat yang lalu, saya masuk ke buku -mansi permainan kegilaan ini. Gim ini agak seperti petunjuk klasik di mana para pemain berkeliaran di sekitar rumah yang mencoba memecahkan beberapa misteri. Ini adalah permainan yang luar biasa yang sangat saya rekomendasikan. Ngomong -ngomong, gim ini menggunakan gulungan dadu untuk menyelesaikan tindakan, dan acara gim lainnya. Anehnya, pemain terkadang harus menggulung lebih banyak dadu daripada game termasuk (6)! Saya memutuskan bahwa ini adalah kesempatan yang sempurna untuk membangun aplikasi roller dadu khusus. Dalam tutorial ini, saya akan menggunakan komponen android dasar untuk membangun rumah -rumah gila -gilaan rol dadu kegilaan.

Aplikasi DICE ini secara khusus dirancang untuk mansions of madness gameplay jadi pertama -tama saya akan menguraikan bagaimana permainan menggunakan dadu.
Agar hal -hal sederhana, aplikasi ini akan menjadi daftar dadu yang vertikal dan dapat digulir. Aplikasi ini akan memiliki 3 tombol untuk memicu fungsi "gulungan dadu", "tambahkan dadu" dan "hapus dadu". Setiap dadu akan memiliki 'tahan' dan 'perubahan' yang sesuai.

Platform Android selalu bergeser, membuat tutorial seperti ini usang dari waktu ke waktu. Untuk referensi, lingkungan dev saya:
Lingkungan Android


Semua nama ini dapat diubah setelah pembuatan proyek meskipun bisa menjadi rumit untuk mengejar semua referensi nama jika proyek menjadi rumit.

Android memiliki banyak versi. Dengan setiap rilis, platform berubah. Ini pada dasarnya berarti ada banyak perangkat Android di dunia dengan versi yang berbeda. Ini menjadi sakit kepala bagi pengembang aplikasi karena tergantung pada perpustakaan apa yang digunakan aplikasi, aplikasi mungkin tidak kompatibel dengan perangkat tertentu. Tradeoff di sini adalah aplikasi yang menggunakan perpustakaan Android baru tidak dapat berjalan pada perangkat yang lebih lama. Jika aplikasi harus berjalan pada perangkat yang lebih lama, aplikasi harus menggunakan beberapa konstruksi Android yang lebih lama.

Template awal sebenarnya tidak terlalu penting untuk aplikasi ini. Kode template terkadang berguna karena prepopulasi tata letak dan kelas awal dengan beberapa kode. Karena saya tidak akan menggunakan semua ini, saya memilih aktivitas kosong.

Dialog Pembuatan Proyek Android menginisialisasi proyek dengan konstruksi dasar:
Gradle adalah kerangka kerja untuk memfasilitasi proyek pembangunan. Di Wikipedia
Manifes Android menggambarkan aplikasi ke Android. Properti aplikasi seperti izin, dan kegiatan. Detail dapat ditemukan di halaman dokumentasi Android.
Untuk memulai, saya menggunakan editor SVG online sederhana bernama Clker untuk menarik wajah dadu sebagai SVG.



Selanjutnya, saya mengimpornya ke proyek saya menggunakan Android Studio's Asset Studio.


Perangkat memiliki resolusi dan dimensi yang berbeda. Memprediksi resolusi dan dimensi perangkat yang dijalankan aplikasi sulit. Menskalakan JPEG dapat menghasilkan grafik buram atau kasar. Salah satu cara untuk mengatasi ini adalah untuk grafik adalah dengan menggunakan SVG. Ada banyak artikel online yang membahas SVG tetapi untuk referensi, silakan lihat artikel Wikipedia SVG untuk informasi lebih lanjut.
Android menawarkan dua cara untuk menggambarkan tata letak: tata letak terprogram dan XML. Menggambarkan tata letak yang kompleks secara terprogram cukup sulit sehingga kebanyakan orang umumnya menghindarinya. Menulis XML mungkin tidak menyenangkan, tetapi Android Studio memang menawarkan beberapa alat untuk meringankan rasa sakit. Alat Pratinjau dan Editor Tata Letak Wsywig. Tetapi bahkan dengan editor, menyelam ke XML hampir tidak bisa dihindari.


Template aktivitas Kosong Android Studio memulai kami dengan elemen tata letak root ConstraintLayout . Kita akan membutuhkan dua komponen di aplikasi ini: area dadu dan area pengontrol. Area dadu akan menjadi daftar dadu yang dapat digulir dan pengontrol akan menjadi 3 tombol "tambahkan" "lepaskan" "roll".

activity_main.xml <?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/dice_list"
android:layout_height="0dp"
android:layout_width="match_parent"
app:layout_constraintBottom_toTopOf="@id/button_bar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</ListView>
<LinearLayout
android:id="@+id/button_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/control_bar_height"
android:orientation="horizontal"
android:weightSum="3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/dice_list">
<Button
android:id="@+id/add_dice_button"
android:layout_gravity = "center"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_button_label"
android:onClick="addDice"/>
<Button
android:id="@+id/rem_dice_button"
android:layout_gravity = "center"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/rem_button_label"
android:onClick="removeDice"/>
<Button
android:id="@+id/roll_dice_button"
android:layout_weight="1"
android:layout_gravity = "center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/roll_button_label"
android:onClick="rollDice"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Bagi mereka yang tidak terbiasa dengan XML, di atas mungkin terlihat seperti omong kosong. Menjelaskan XML berada di luar ruang lingkup tutorial ini, tetapi Google, YouTube, dan Wikipedia adalah sumber daya yang bagus bagi mereka yang mencari informasi lebih lanjut. Untuk tata letak ini saya menggunakan kelas ListView , Button , LinearLayout , dan ConstraintLayout . Detail di sekitar atribut mereka dapat ditemukan di halaman dokumentasi Android.
Saya mencari Layout yang dengan mudah menggambarkan area bawah ketinggian tetap (untuk tombol) dan area atas (untuk dadu) yang mengisi ruang layar yang tersedia. LinearLayout Spaces keluar sub elemennya menggunakan bobot membuatnya tidak cocok. RelativeLayout tidak menawarkan kemampuan untuk 'mengisi ruang yang tersisa' juga membuatnya tidak cocok.
Secara visual, LinearLayout terlihat cukup dekat dengan apa yang saya butuhkan. Namun, LinearLayout adalah untuk daftar elemen statis daripada daftar dinamis. Untuk aplikasi ini, daftar dadu dapat memiliki antara 0 dan 25 dadu, membuat ListView adalah kandidat yang lebih baik.
Nilai 0dp spesifik untuk ConstraintLayout yang menunjukkan bahwa ia harus mengisi ruang yang tersisa dari induk.
Seperti dijelaskan di atas, setiap baris dadu mencakup 2 tombol dan gambar dadu.

row.xml <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/row_height">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/row_height"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:padding="@dimen/row_padding">
<Button
android:id="@+id/dice_change_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/change_button_label">
</Button>
</FrameLayout>
<ImageView
android:id="@+id/dice_icon"
android:layout_centerInParent="true"
android:layout_width="@dimen/image_width"
android:layout_height="@dimen/image_height"
android:src="@drawable/blank_dice"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/row_height"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:padding="@dimen/row_padding">
<Button
android:id="@+id/dice_hold_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hold_button_label">
</Button>
</FrameLayout>
</RelativeLayout>
Tombol terletak di pusat vertikal baris dan agak jauh dari setiap tepi. Saya merasa bahwa desain akan lebih bersih jika desain memisahkan elemen tombol yang sebenarnya dan posisinya di tata letak. Jadi untuk aplikasi saya, saya menggunakan FrameLayout untuk menentukan posisi dan memusatkan tombol di tata letak itu.
Nilai string dan dimensi memungkinkan kita untuk tidak menulis string konfigurasi dan bilangan bulat langsung ke kode. Untuk aplikasi kecil kami, mungkin bukan masalah besar.
string.xml <resources>
<string name="app_name">DiceRoller</string>
<string name="hold_button_label">Hold</string>
<string name="change_button_label">Change</string>
<string name="add_button_label">ADD</string>
<string name="rem_button_label">REM</string>
<string name="roll_button_label">ROLL</string>
</resources>
dimens.xml <?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="row_height">72dp</dimen>
<dimen name="row_padding">16dp</dimen>
<dimen name="control_bar_height">72dp</dimen>
<dimen name="image_width">72dp</dimen>
<dimen name="image_height">72dp</dimen>
</resources>
ListView dan ArrayAdapter Pada titik ini, saya telah menginisialisasi proyek Android kami dengan mainaktivitas kosong dan mengejek beberapa tata letak. Selanjutnya, saya akan masuk ke logika dan kode. Untuk memulai, saya ingin masuk ke beberapa kelas Java spesifik android spesifik. ListView adalah kelas tata letak dasar untuk membuat daftar visual. Kerangka Android memisahkan komponen visual ( ListView ) dan komponen data ( List<Dice> ) dengan menggunakan pola adaptor. Dalam kasus kami, semua adaptor lakukan adalah memetakan data ( Dice ) ke beberapa tata letak visual ( dice_row.xml ). Dalam hal ini, file tata letak XML menjelaskan tata letak.
MainActivity.java public class MainActivity extends AppCompatActivity {
DiceAdapter diceAdapter;
List <Dice> diceList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//associating activity to layout
setContentView(R.layout.activity_main);
//Setup ListView and Adapter
ListView listView = findViewById(R.id.dice_list);
diceAdapter = new DiceAdapter(this, R.layout.dice_row, diceList);
listView.setAdapter(diceAdapter);
//Initialize Data
diceAdapter.add(new Dice());
}
public class DiceAdapter extends ArrayAdapter<Dice> {
public DiceAdapter(@NonNull Context context, int resource, List<Dice> list) {
super(context, resource, list);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.dice_row, parent, false);
}
return convertView;
}
}
}
Aplikasi ini akan mewakili keadaan dadu dengan objek dadu. Objek Dice memiliki dua properti: nilai dadu [kosong, diperbesar, bintang], dan apakah dadu 'dipegang'. Secara fungsional, dadu memiliki metode roll yang secara acak akan memilih wajah dadu. Akhirnya, saya menambahkan metode yang mengubah nilai dadu ke daftar berikutnya.
MainActivity.java ....
public static class Dice {
public enum Face {
BLANK,
MAGNIFY,
STAR
}
public static Random random = new Random();
boolean hold = false;
Face diceVal;
Dice() {
roll();
}
public void roll() {
int num = random.nextInt(4);
if(num == 0) { //25% magify
this.diceVal = Face.MAGNIFY;
} else {
//37.5% star, 37.5% blank
if(random.nextBoolean()) {
this.diceVal = Face.BLANK;
} else {
this.diceVal = Face.STAR;
}
}
}
public void toggleHold() {
hold = !hold;
}
public void nextValue() {
int index = diceVal.ordinal();
index = (index+1) % Face.values().length;
diceVal = Face.values()[index];
}
}
Pada langkah ini saya memetakan tombol klik ke logika. Platform Android menawarkan beberapa cara untuk melakukan ini. Salah satu caranya adalah dengan menentukan atribut dari file tata letak. Lain adalah mengatur secara terprogram onClickListener . Di aplikasi kami, gunakan pendekatan atribut untuk tiga tombol level atas dan atur secara terprogram untuk pendengar untuk tombol baris.
addDice Jika jumlah dadu kurang dari 25, tambahkan objek dadu baru ke daftar dadu.
Desain
activity_main.xml ....
<Button
android:id="@+id/add_dice_button"
android:layout_gravity = "center"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_button_label"
android:onClick="addDice"/>
....
Logika
MainActivity.java ....
public void addDice(View view) {
if(diceList.size()< MAX_DICE_COUNT) {
diceAdapter.add(new Dice());
}
}
....
removeDice jika daftar dadu tidak kosong, menghapus dadu terakhir dari daftar
Desain
activity_main.xml ....
<Button
android:id="@+id/rem_dice_button"
android:layout_gravity = "center"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/rem_button_label"
android:onClick="removeDice"/>
....
Logika
MainActivity.java ....
public void removeDice(View view) {
if(!diceList.isEmpty()) {
int lastIndex = diceList.size() - 1;
diceAdapter.remove(diceAdapter.getItem(lastIndex));
}
}
....
rollDice mengulang nilai setiap dadu pada daftar yang belum ditandai untuk dipegang.
Desain
activity_main.xml ....
<Button
android:id="@+id/roll_dice_button"
android:layout_weight="1"
android:layout_gravity = "center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/roll_button_label"
android:onClick="rollDice"/>
....
Logika
MainActivity.java ....
public void rollDice(View view) {
//roll all dice
for(Dice dice : diceList) {
if(!dice.hold)
dice.roll();
}
//notify adapter to update view
diceAdapter.notifyDataSetChanged();
}
....
notifyDataSetChanged ? Tombol roll mengubah dicevalue untuk objek dadu yang sesuai. Karena pemisahan pola tampilan/adaptor data, tata letak baris dadu tidak secara otomatis membuat ulang kecuali dipicu. Memanggil notifyDataSetChanged menggambar ulang tampilan.
Mengklik tombol hold akan mengatur bendera penahan dadu.
MainActivity.java ....
Button holdButton = convertView.findViewById(R.id.dice_hold_button);
holdButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Dice dice = diceList.get(position);
dice.toggleHold();
}
});
....
Mengklik tombol Tahan akan mengubah nilai Dice dan memperbarui antarmuka.
MainActivity.java ....
Button changeButton = convertView.findViewById(R.id.dice_change_button);
changeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Dice dice = diceList.get(position);
dice.nextValue();
diceAdapter.notifyDataSetChanged();
}
});
....