افضل طريقة لإنشاء تطبيق Wordle في Jetpack Compose
من أجل التعرف على Jetpack Compose ، مكتبة Android الجديدة
لإنشاء واجهات المستخدم ، سنقوم بإنشاء نسخة طبق الأصل من هذا التطبيق المعروف.
طريقة إنشاء تطبيق Wordle على Jetpack Compose
الجزء 1: لنبدأ بالمجال والمكون المرئي الأول لتطبيق Wordle الخاص بنا
حتى الآن ، ربما تكون قد سمعت عن Wordle ، وهو تطبيق اكتسب شعبية
في أواخر عام 2021 ويستمر في جذب الآلاف من المستخدمين حتى يومنا هذا.
من أجل الكشف عن كيفية عمله والتعرف على Jetpack Compose ،
مكتبة Android الجديدة لإنشاء واجهات المستخدم ، سنقوم بإنشاء
نسخة طبق الأصل من هذا التطبيق المعروف.
سنبدأ في تصميم مجالنا بالجزء الأساسي منه ؛ سنقوم بنمذجة كيف نريد تمثيل الحروف.
نظرًا لأن الحالة الأولية للعبتنا ستكون لوحة 6 × 5 (وستكون هذه اللوحة
فارغة في البداية وتملأ شيئًا فشيئًا) ، يمكننا تمثيل هذه الخلايا كفئة مختومة مثل:
sealed class WordleLetter(open val letter: String) {
object EmptyWordleLetter : WordleLetter("")
data class FilledWordleLetter(override val letter: String) : WordleLetter(letter)
يمكننا أيضًا إضافة تحقق إلى كيان FilledWordleLetter نظرًا للراحة ،
فنحن نمثل سمة letter كسلسلة. سنبحث عنه ليكون له حرف واحد فقط ،
والذي يمكننا من أجله إضافة هذا التحقق في المُنشئ ورمي استثناء في حالة عدم الوفاء به:
if (letter.count() != 1) {
throw IllegalArgumentException("A WordleLetter can have one letter at most")
}
بالإضافة إلى ذلك ، نحتاج أيضًا إلى تمثيل حالة كل حرف على السبورة. لهذا ، سوف نستخدم فئة التعداد مثل:
enum class LetterStatus {
EMPTY,
NOT_CHECKED,
NOT_INCLUDED,
INCLUDED,
MATCH
}
لاحقًا ، سنضيف أيضًا الألوان التي سنرسم بها كل خلية ، بما يتوافق مع كل حالة من حالاتها المحتملة.
الآن لدينا تمثيل أساسي لرسائلنا وحالاتها المحتملة ، يمكننا البدء في بناء الكيانات
المختلفة التي ستمثل كل مكون من مكونات لوحتنا ، بدءًا من الأحرف مرة أخرى.
لهذا ، يمكننا إنشاء كيان يمثل حرفًا مع حالته ، مثل:
data class BoardLetter(
val letter: WordleLetter,
val state: LetterStatus
)
سيتم تشكيل كل صف من صفوف اللوحة بواسطة قائمة <BoardLetter>
يمكننا استدعاء BoardRow ، وسيتم تشكيل اللوحة الكاملة بواسطة قائمة <BoardRow> .
سنبني هذه الكيانات لاحقًا ، لكن في الوقت الحالي ، يكفي أن نعرف أن هذا سيكون تمثيلهم.
إذا انتبهنا لهذا التنفيذ ، يمكننا أن نرى أنه في الواقع ، فإن اللوحة عبارة عن
مصفوفة من List <List <BoardLetter>> ، ولكن نظرًا لأننا نحتاج إلى إضافة
وظائف إلى كل مكون من هذه المصفوفة ، فقد فضلت تقسيمها إلى
فئات ملموسة لجعل التنفيذ أسهل وأكثر وضوحًا.
لكن دعونا لا نتقدم كثيرًا على أنفسنا حتى الآن ؛ في الوقت الحالي ،
لدينا تمثيل لحرف مع حالته على السبورة ، لذلك دعونا نبدأ في إضافة وظائف إلى هذه الفئة.
أول شيء نريد أن نكون قادرين على فعله باستخدام رسالة المجلس هو
أن نكون قادرين على كتابة خطاب ، ولكن كيف يمكننا القيام بذلك إذا كان
جميع أعضاء كياننا غير قابلين للتغيير؟ سهل! لذلك ، استخدمنا فئة بيانات
تزودنا بالطريقة .copy والتي من خلالها بدلاً من تغيير كياننا ، سننشئ
مثيلًا جديدًا من نفس الكائن ولكن مع التعديلات التي حددناها. بالإضافة إلى ذلك ،
تمامًا كما نريد إضافة أحرف ، سنرغب في إزالتها ، وسنفعل نفس الشيء تمامًا
كما هو الحال مع الإنشاء ، باستخدام طريقة النسخ التي تسمح لنا بالحفاظ على ثبات كياننا.
fun setLetter(aLetter: String) =
copy(
letter = WordleLetter.FilledWordleLetter(aLetter),
state = LetterStatus.NOT_CHECKED)
fun deleteLetter() =
copy(
letter = WordleLetter.EmptyWordleLetter,
state = LetterStatus.EMPTY)
أخيرًا ، سنضيف أيضًا طريقة ملائمة لتكون قادرًا على إنشاء أحرف فارغة لبدء العمل منها.
سننشئ هذه الطريقة داخل كائن مصاحب لنتمكن من
استدعائها دون الحاجة إلى وجود مثيل للفئة.
fun empty() = BoardLetter(WordleLetter.EmptyWordleLetter, LetterStatus.EMPTY)
رائعة! لدينا بالفعل كياننا الذي يمثل حرفًا في لعبتنا ،
بالإضافة إلى تقريب أولي للوظيفة التي سنحتاجها خلال تطورنا.
لا يمكننا أن ننسى كتابة الاختبارات لهذا الفصل. لن أخوض في التفاصيل
لأنها تافهة لهذا التنفيذ ، ولكن يمكن استشارتهم هنا.
الآن بعد أن أصبح لدينا تنفيذ مجالنا جاهزًا ، يمكننا إنشاء تمثيل Jetpack Compose له.
لذلك ، سنقوم بإنشاء Composable يسمى LetterBox
والذي سيتلقى كمعامل الحرف الذي نريد رسمه:
@Composable
fun LetterBox(
letter: WordleLetter,
state: LetterStatus
)
نريد من هذا المكون إظهار الحرف المعني الذي كتبه المستخدم ، ونريد أيضًا
رسم خلفيته بلون مختلف اعتمادًا على حالة الحرف. إن أبسط طريقة لتكرار
هذا السلوك هي إضافة الخلفية مباشرة إلى نص قابل للإنشاء . ومع ذلك ،
لجعلها تبدو أكثر أناقة ، سنستخدم بطاقة بحيث يبدو المكون الخاص بنا كما يلي:
@Composable
fun LetterBox(
letter: WordleLetter,
state: LetterStatus
){
Card(
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(containerColor = calculateState(state)),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
modifier = Modifier.aspectRatio(1f)
) {
Text(
modifier = Modifier
.fillMaxSize()
.wrapContentHeight(),
text = letter.letter,
textAlign = TextAlign.Center
)
}
}
private fun mapToBackgroundColor(state: LetterStatus) =
when (state) {
EMPTY, NOT_CHECKED -> Color.White
NOT_INCLUDED -> Color.LightGray
INCLUDED -> Color.Yellow
MATCH -> Color.Green
}
سنستفيد من هذا المكون لتعيين الحالات المختلفة لكل مربع بلون مختلف ، باتباع قواعد اللعبة.
بمجرد إنشاء هذا المكون ، يمكننا تصوره بفضل Preview of Compose .
@Preview
@Composable
fun Preview() {
LetterBox(
letter = WordleLetter.FilledWordleLetter("A"),
state = INCLUDED
)
}
الكثير بالنسبة لهذه الدفعة الأولى حول إنشاء شيء مشابه لتطبيق
Wordle باستخدام Jetpack Compose. في المقالات المستقبلية ،
سننشئ كل صف من صفوف لوحتنا التي ستتألف من المكونات التي أنشأناها هنا ،
وسننشئ أخيرًا لوحة اللعبة الكاملة ، جنبًا إلى جنب مع قاموس لتحميل الكلمات
التي سنستخدمها وكل المنطق المتعلقة باللعبة.
يمكن العثور على الكود الكامل للتطبيق بأكمله على هذا الرابط.