Android Kotlin Fundamentals 02.2: إضافة تفاعل المستخدم

يشكّل هذا الدرس التطبيقي جزءًا من الدورة التدريبية لأساسيات Android Kotlin. ستحصل على أقصى قيمة ممكنة من هذه الدورة التدريبية إذا كنت تستخدم الدروس التطبيقية حول الترميز بشكل متسلسل. يتم إدراج جميع الدروس التطبيقية حول ترميز الدورات التدريبية في الصفحة المقصودة لدروس الترميز Android Kotlin Fundamentals.

ما يجب معرفته

  • إنشاء تطبيق أساسي متوافق مع Android في Kotlin.
  • تشغيل تطبيق متوافق مع Android على محاكي أو جهاز
  • إنشاء تنسيق خطي باستخدام "استوديو التطبيقات" في "استوديو Android"
  • إنشاء تطبيق بسيط يستخدم LinearLayout وTextView وScrollView وزر يحتوي على معالِج للنقرات

ما ستتعرَّف عليه

  • كيفية الحصول على إدخال من قِبل المستخدم باستخدام ملف شخصي في EditText.
  • كيفية ضبط النص في طريقة عرض TextView باستخدام النص من طريقة العرض EditText
  • طريقة العمل مع View وViewGroup
  • كيفية تغيير مستوى رؤية View

الإجراءات التي ستنفذّها

  • يمكنك إضافة تفاعل إلى تطبيق aboutMe الذي يكون من درس تطبيقي سابق حول الترميز.
  • أضِف EditText حتى يتمكن المستخدم من إدخال نص.
  • أضِف Button ونفِّذ معالِج النقرة.

في هذا الدرس التطبيقي حول الترميز، يمكنك توسيع نطاق تطبيق "لمحة عني" لإضافة تفاعل المستخدم. عليك إضافة حقل لقب وزر تم وعرض نص لعرض اللقب. بعد إدخال المستخدم لقب والنقر على الزر تم، يتم تحديث عرض النص لإظهار اللقب الذي تم إدخاله. يمكن للمستخدم تحديث اللقب من خلال النقر على طريقة عرض النص.

لمحة عن التطبيق

في هذه المهمة، أضِف حقل إدخال EditText للسماح للمستخدم بإدخال لقب.

الخطوة 1: تنفيذ الخطوات الأولى

  1. إذا لم يكن لديك تطبيق aboutMe من درس تطبيقي سابق، عليك تنزيل رمز المبتدئين AboutMeInteractive-Starter. هذا هو الرمز نفسه الذي انتهيت منه في درس تطبيقي سابق حول الترميز.
  2. افتح مشروع aboutMeInteractive-Starter في "استوديو Android".
  3. شغِّل التطبيق. يمكنك الاطّلاع على عرض نص الاسم وصورة نجمة وجزء طويل من النص في طريقة عرض التمرير.



    لاحظ أن المستخدم لا يمكنه تغيير أي من النصوص.

تكون التطبيقات أكثر إثارة للاهتمام إذا كان بإمكان المستخدم التفاعل مع التطبيق، مثلاً في حال كان المستخدم يمكنه إدخال النص. لقبول إدخال النص، يوفّر نظام التشغيل Android واجهة مستخدم (UI) تُسمى تعديل النص. أنت تحدّد نصًا للتعديل باستخدام السمة EditText، وهي فئة فرعية من TextView. يسمح نص التعديل للمستخدم بإدخال إدخال النص وتعديله، كما هو موضح في لقطة الشاشة أدناه.

الخطوة 2: إضافة EditText

  1. في "استوديو Android"، افتح ملف التنسيق activity_main.xml في علامة التبويب التصميم.
  2. في لوحة لوحة الألوان، انقر على نص.



    Ab TextView، وهو TextView، ويظهر في أعلى قائمة عناصر النص في لوحة لوحة الألوان. أسفل Ab TextView هناك طرق عرض EditText متعددة.

    في جزء لوحة الألوان، لاحظ كيف يعرض رمز TextView الأحرف Ab بدون علامة سفلية. ومع ذلك، تعرض رموز EditText الشرطة المائلة. يشير التقييم الفرعي إلى أنّ العرض قابل للتعديل.

    في كل طريقة عرض EditText، يضبط Android سمات مختلفة ويعرض النظام أسلوب الإدخال الصوتي المناسب (مثل لوحة مفاتيح على الشاشة).
  3. اسحب نص تعديل PlainText إلى شجرة العناصر وضعه أسفل name_text وأعلى star_image.


  4. استخدِم جزء السمات لضبط السمات التالية في الملف الشخصي EditText.

السمة

القيمة

id

nickname_edit

layout_width

match_parent (تلقائي)

layout_height

wrap_content (تلقائي)

  1. شغِّل تطبيقك. فوق صورة النجمة، سيظهر لك نص تعديل يحتوي على النص التلقائي &quot؛الاسم&quot؛.


في هذه المَهمة، يمكنك تعديل نمط EditText عن طريق إضافة تلميح وتغيير محاذاة النص وتغيير النمط إلى NameStyle وضبط نوع الإدخال.

الخطوة 1: إضافة نص تعديل

  1. أضف موردًا جديدًا للسلسلة إلى التلميح في ملف string.xml.
<string name="what_is_your_nickname">What is your Nickname?</string>
  1. استخدِم جزء السمات لضبط السمات التالية على عرض EditText:

السمة

القيمة

style

NameStyle

textAlignment

(الوسط)

hint

@string/what_is_your_nickname

  1. في جزء السمات، أزِل القيمة Name من السمة text. ويجب أن تكون قيمة السمة text فارغة حتى يتم عرض التلميح.

الخطوة 2: إعداد سمة InputType

تحدّد السمة inputType نوع الإدخال الذي يمكن للمستخدمين إدخاله في الملف الشخصي EditText. يعرض نظام Android حقل الإدخال المناسب ولوحة المفاتيح على الشاشة بناءً على نوع الإدخال الذي تم ضبطه.

للاطّلاع على جميع أنواع الإدخال الممكنة، في لوحة السمات، انقر على حقل inputType، أو انقر على رمز النقاط الثلاث ... بجانب الحقل. ستُفتح قائمة توضح جميع أنواع الإدخالات التي يمكنك استخدامها، مع تحديد نوع الإدخال النشط حاليًا. يمكنك اختيار أكثر من نوع إدخال واحد.

على سبيل المثال، بالنسبة إلى كلمات المرور، استخدِم القيمة textPassword. يخفي حقل النص إدخال المستخدم.

وبالنسبة إلى أرقام الهواتف، استخدِم القيمة phone. يتم عرض لوحة مفاتيح الأرقام، ويمكن للمستخدم إدخال أرقام فقط.

ضبط نوع الإدخال لحقل اللقب:

  1. ضبط السمة inputType على textPersonName لنص تعديل nickname_edit.
  2. في جزء شجرة المكوّنات، لاحظ تحذير autoFillHints. لا ينطبق هذا التحذير على هذا التطبيق وخارج نطاق هذا الدرس التطبيقي حول الترميز، لذا يمكنك تجاهله. (إذا كنت تريد معرفة المزيد من المعلومات عن الملء التلقائي، راجع تحسين تطبيقك للملء التلقائي.)
  3. في لوحة السمات، تحقق من قيم السمات التالية للملف الشخصي EditText:

السمة

القيمة

id

nickname_edit

layout_width

match_parent (تلقائي)

layout_height

wrap_content (تلقائي)

style

@style/NameStyle

inputType

textPersonName

hint

"@string/what_is_your_nickname"

text

(فارغ)

Button هي عنصر في واجهة المستخدم يمكن للمستخدم النقر عليه لتنفيذ إجراء. يمكن أن يتضمن الزر نصًا أو رمزًا أو نصًا ورمزًا معًا.

في هذه المهمة، يمكنك إضافة الزر تم الذي ينقر عليه المستخدم بعد إدخال لقبه. يستبدل الزر عرض EditText بعرض TextView الذي يعرض اللقب. لتعديل اللقب، يمكن للمستخدم النقر على الملف الشخصي TextView.

الخطوة 1: إضافة زر "تم"

  1. اسحب زرًا من لوحة لوحة الألوان إلى شجرة المكوّنات. ضع الزر أسفل نص تعديل nickname_edit.

  2. أنشئ موردًا جديدًا لسلسلة بعنوان done. امنح السلسلة قيمة Done،
<string name="done">Done</string>
  1. استخدم جزء السمات لتعيين السمات التالية في طريقة عرض Button المضافة حديثًا:

السمة

القيم

id

done_button

text

@string/done

layout_gravity

center_horizontal

layout_width

wrap_content

تعمل السمة layout_gravity على توسيط العرض في تنسيقه الرئيسي، LinearLayout.

  1. يمكنك تغيير النمط إلى Widget.AppCompat.Button.Colored، وهو نمط من الأنماط المُحدَّدة مسبقًا التي يوفّرها Android. يمكنك اختيار النمط من القائمة المنسدلة أو من نافذة الموارد.



    يغير هذا النمط لون الزر إلى لون التمييز، colorAccent. يتم تحديد لون التمييز في ملف res/values/colors.xml.


يحتوي ملف colors.xml على الألوان التلقائية لتطبيقك. يمكنك إضافة موارد ألوان جديدة أو تغيير موارد الألوان الحالية في مشروعك، استنادًا إلى متطلبات تطبيقك.

نموذج لملف colors.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <color name="colorPrimary">#008577</color>
   <color name="colorPrimaryDark">#00574B</color>
   <color name="colorAccent">#D81B60</color>
</resources>

الخطوة 2: إضافة نمط الزر "تم"

  1. في جزء السمات، أضف هامشًا علويًا من خلال اختيار Layout_Margin > Top. ضبط الهامش العلوي على layout_margin، وهو محدّد في ملف dimens.xml.


  2. اضبط السمة fontFamily على roboto من القائمة المنسدلة.


  3. بدِّل إلى علامة التبويب Text (النص) وتحقق من رمز XML الذي تم إنشاؤه للزر الذي تمت إضافته مؤخرًا.
<Button
   android:id="@+id/done_button"
   style="@style/Widget.AppCompat.Button.Colored"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center_horizontal"
   android:layout_marginTop="@dimen/layout_margin"
   android:fontFamily="@font/roboto"
   android:text="@string/done" />

الخطوة 3: تغيير مورد الألوان

في هذه الخطوة، يمكنك تغيير لون التمييز ليتناسب مع شريط تطبيقات نشاطك.

  1. افتح res/values/colors.xml وغيِّر قيمة colorAccent إلى #76bf5e.
<color name="colorAccent">#76bf5e</color>

يمكنك رؤية اللون المتوافق مع رمز HEX، في أعلى يمين محرّر الملفات.

لاحِظ التغيير في لون الزر في محرِّر التصميم.

  1. شغِّل تطبيقك. ومن المفترَض أن يظهر لك الزر تمّ أسفل نص التعديل.


بعد إدخال المستخدم لقب والنقر على الزر تم، يظهر اللقب في عرض TextView. في هذه المهمة، يمكنك إضافة عرض نصي بخلفية ملونة. يُظهر عرض النص لقب المستخدم أعلى star_image.

الخطوة 1: إضافة TextView للاسم

  1. اسحب عرض النص من جزء لوحة الألوان إلى شجرة المكوّنات. ضع عرض النص أسفل done_button وأعلى star_image.


  2. استخدم جزء السمات لتعيين السمات التالية للملف الشخصي الجديد TextView:

السمة

القيمة

id

nickname_text

style

NameStyle

textAlignment

(الوسط)

الخطوة 2: تغيير حق الوصول إلى TextView

يمكنك إظهار الملفات الشخصية في تطبيقك أو إخفاؤها باستخدام السمة visibility. تأخذ هذه السمة إحدى القيم الثلاث التالية:

  • visible: العرض مرئي.
  • Invisible: يؤدي هذا الخيار إلى إخفاء العرض، ولكنه ما زال يشغل مساحة في التنسيق.
  • gone: يخفي العرض، ولا تشغل مساحة العرض أي مساحة.
  1. في لوحة السمات، اضبط visibility لعرض النص nickname_text على gone، لأنك لا تريد أن يُظهر تطبيقك عرض النص هذا أولاً.



    لاحظ أنه عند تغيير السمة في لوحة السمات، سيختفي عرض nickname_text من محرِّر التصميم. تم إخفاء طريقة العرض في معاينة التنسيق.
  2. غيِّر قيمة السمة text للملف الشخصي nickname_text إلى سلسلة فارغة.

يجب أن يظهر رمز XML الذي تم إنشاؤه لجهاز TextView هذا على النحو التالي:

<TextView
   android:id="@+id/nickname_text"
   style="@style/NameStyle"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:textAlignment="center"
   android:visibility="gone"
   android:text="" />

من المفترض أن تبدو معاينة التنسيق على النحو التالي:

يحدد معالج النقر على الكائن Button (أو على أي ملف شخصي) الإجراء الذي سيتم تنفيذه عند النقر على الزر (عرض). ويجب تنفيذ الدالة التي تعالج حدث النقر في Activity الذي يستضيف التنسيق باستخدام الزر (عرض).

وبوجهٍ عام، يكون للمستمع الذي ينقر على الإعلان هذا التنسيق، حيث تكون المشاهدة التي تمت مشاهدتها هي النقرة التي تلقّت النقرة أو النقرة.

private fun clickHandlerFunction(viewThatIsClicked: View) {
// Add code to perform the button click event
}

يمكنك إرفاق دالة الاستماع إلى النقرات بأحداث النقر على الزر بطريقتين:

  • في تنسيق XML، يمكنك إضافة السمة android:onClick إلى العنصر <Button>. مثلاً:
<Button
   android:id="@+id/done_button"
   android:text="@string/done"
   ...
   android:onClick="clickHandlerFunction"/>

أو

  • يمكنك إجراء ذلك آليًا في وقت التشغيل في onCreate() من Activity عن طريق الاتصال بـ setOnClickListener. مثلاً:
myButton.setOnClickListener {
   clickHanderFunction(it)
}

في هذه المهمة، يمكنك إضافة أداة معالجة نقرة لـ done_button آليًا. أضِف المستمع عند النقر على النشاط المقابل، وهو MainActivity.kt.

ستنفذ وظيفة مُستمعة النقرات التي تُسمى addNickname ما يلي:

  • الحصول على النص من نص تعديل nickname_edit
  • ضبط النص في طريقة عرض النص nickname_text.
  • إخفاء نص التعديل والزر.
  • عرض اللقب TextView

الخطوة 1: إضافة أداة معالجة النقر

  1. في "استوديو Android"، في مجلد java، افتح الملف MainActivity.kt.
  2. في MainActivity.kt، داخل الصف MainActivity، أضِف دالة addNickname. يجب تضمين معلمة إدخال من النوع View بدلاً من view. المعلَمة view هي View التي يتم استدعاء الدالة فيها. في هذه الحالة، سيكون view مثيلًا للزر تم.
private fun addNickname(view: View) {
}
  1. داخل الدالة addNickname، استخدِم findViewById() للحصول على مرجع لنص تعديل nickname_edit وعرض النص nickname_text.
val editText = findViewById<EditText>(R.id.nickname_edit)
val nicknameTextView = findViewById<TextView>(R.id.nickname_text)
  1. تتيح ضبط النص في عرض nicknameTextView للنص على النص الذي أدخله المستخدم في editText من خلال text.
nicknameTextView.text = editText.text
  1. يمكنك إخفاء الاسم المستعار EditText من خلال ضبط الخاصية visibility على editText على View.GONE.

في مهمة سابقة، غيّرت السمة visibility باستخدام "محرر التنسيق". ويمكنك هنا تنفيذ الشيء نفسه آليًا.

editText.visibility = View.GONE
  1. يجب إخفاء زر تم من خلال ضبط الخاصية visibility على View.GONE. لديك مرجع للزر باعتباره معلمة إدخال الدالة view.
view.visibility = View.GONE
  1. في نهاية الدالة addNickname، اجعل اللقب TextView مرئيًا من خلال ضبط الخاصية visibility على View.VISIBLE.
nicknameTextView.visibility = View.VISIBLE

الخطوة 2: إرفاق أداة معالجة النقر بالزر "تم"

الآن وبعد أن أنشأت وظيفة تحدد الإجراء الذي سيتم تنفيذه عند النقر على الزر تم، يجب إرفاق الوظيفة بالملف الشخصي Button.

  1. في MainActivity.kt، في نهاية الدالة onCreate()، احصل على مرجع إلى العرض تمButton. استخدِم الدالة findViewById() واستدعِ setOnClickListener. يمكنك تقديم مرجع إلى دالة "مستمع النقرات"، addNickname().
findViewById<Button>(R.id.done_button).setOnClickListener {
            addNickname(it)
        }

في الرمز أعلاه، يشير it إلى done_button، وهو المشاهدة التي يتم تمريرها كوسيطة.

  1. شغِّل تطبيقك وأدخِل لقبًا وانقر على الزر تمّ. لاحِظ كيف يتم استبدال نص التعديل والزر بعرض نص الاسم.

تجدر الإشارة إلى أنه حتى بعد أن ينقر المستخدم على الزر تم، تظل لوحة المفاتيح مرئية. هذا السلوك هو الإعداد التلقائي.

الخطوة 3: إخفاء لوحة المفاتيح

في هذه الخطوة، يمكنك إضافة رمز لإخفاء لوحة المفاتيح بعد أن ينقر المستخدم على الزر تم.

  1. في MainActivity.kt، في نهاية الدالة addNickname()، أضِف الرمز التالي. إذا كنت تريد الحصول على مزيد من المعلومات عن كيفية عمل هذا الرمز، اطّلِع على مستندات hideSoftInputFromWindow.
// Hide the keyboard.
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
  1. شغِّل تطبيقك مرة أخرى. يُرجى ملاحظة أنه بعد النقر على تم، تكون لوحة المفاتيح مخفية.

وما من طريقة للمستخدم لتغيير اللقب بعد النقر على الزر تم. في المهمة التالية، يمكنك جعل التطبيق أكثر تفاعلاً وإضافة وظائف حتى يتمكن المستخدم من تحديث الاسم.

في هذه المهمة، يمكنك إضافة مستمع نقر إلى عرض نص اللقب. وتخفي أداة معالجة نقر النقرة عرض نص اللقب وتُظهر نص التعديل وتعرض الزر تم.

الخطوة 1: إضافة أداة معالجة النقر

  1. في MainActivity، عليك إضافة دالة قائمة النقرات التي تحمل الاسم updateNickname(view: View) لعرض نص اللقب.
private fun updateNickname (view: View) {
}
  1. داخل الدالة updateNickname، احصل على مرجع لنص التعديل nickname_edit، واحصل على مرجع للزر تم. ولإجراء ذلك، استخدِم الطريقة findViewById().
val editText = findViewById<EditText>(R.id.nickname_edit)
val doneButton = findViewById<Button>(R.id.done_button)
  1. في نهاية الدالة updateNickname، أضِف الرمز لإظهار نص التعديل، واعرض الزر تم، وأخفي عرض النص.
editText.visibility = View.VISIBLE
doneButton.visibility = View.VISIBLE
view.visibility = View.GONE
  1. في MainActivity.kt، في نهاية دالة onCreate()، يمكنك استدعاء setOnClickListener في عرض النص nickname_text. ويمكنك الإشارة إلى مرجع دالة "استماع النقرات"، وهو updateNickname().
findViewById<TextView>(R.id.nickname_text).setOnClickListener {
   updateNickname(it)
}
  1. شغِّل تطبيقك. أدخِل لقبًا، وانقر على الزر تمّ، ثم انقر على طريقة عرض TextView. عندما يختفي عرض اللقب، يظهر نص التعديل والزر تم.


يُرجى العِلم أنّ طريقة العرض EditText لا يتم التركيز عليها تلقائيًا ولا تظهر لوحة المفاتيح. من الصعب على المستخدم معرفة أن عرض نص اللقب يمكن النقر عليه. في المهمة التالية، يمكنك إضافة تركيز ونمط إلى عرض نص اللقب.

الخطوة 2: ضبط التركيز على عرض EditText وإظهار لوحة المفاتيح

  1. في نهاية الدالة updateNickname، اضبط التركيز على عرض EditText. استخدام طريقة requestFocus()
// Set the focus to the edit text.
editText.requestFocus()
  1. في نهاية الدالة updateNickname، أضِف الرمز لجعل لوحة المفاتيح مرئية.
// Show the keyboard.
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(editText, 0)

الخطوة 3: إضافة لون الخلفية إلى اسم الاجتماع

  1. ضبط لون خلفية عرض النص nickname_text على @color/colorAccent وإضافة مساحة متروكة لأسفل تبلغ @dimen/small_padding. ستعرض هذه التغييرات كتلميح للمستخدم بأن عرض نص اللقب قابل للنقر.
android:background="@color/colorAccent"
android:paddingBottom="@dimen/small_padding"
  1. شغِّل تطبيقك النهائي. ويكون نص التعديل محل التركيز، ويتم عرض اللقب في نص التعديل، كما يتم تصميم عرض نص اللقب.

والآن، استعِد صديقًا لتطبيق "نبذة عني" التفاعلي.

مشروع "استوديو Android": لمحة عن MeMeInteractive

  • أداة محرر التنسيق في "استوديو Android" هي محرِّر تصميم مرئي. يمكنك استخدام محرر التنسيق لإنشاء تنسيق تطبيقك عن طريق سحب عناصر واجهة المستخدم إلى التنسيق.
  • EditText هو عنصر في واجهة المستخدم يسمح للمستخدم بإدخال نص وتعديله.
  • Button هي عنصر في واجهة المستخدم يمكن للمستخدم النقر عليه لتنفيذ إجراء. يمكن أن يتضمن الزر نصًا أو رمزًا أو نصًا ورمزًا معًا.

أدوات معالجة النقرات

  • يمكنك جعل أيّ View ردًّا على السؤال من خلال إضافة مستمع للنقر عليه.
  • الدالة التي تعرّف المستمع عند النقر تتلقى View التي يتم النقر عليها.

يمكنك إرفاق دالة سماع النقرات بـ View بأي من الطريقتين التاليتين:

دورة Udacity:

مستندات مطوّر برامج Android:

يسرد هذا القسم المهام الدراسية المحتملة للطلاب الذين يعملون من خلال هذا الدرس التطبيقي حول الترميز في إطار دورة تدريبية يُديرها معلِّم. يجب أن ينفِّذ المعلّم ما يلي:

  • يمكنك تخصيص واجب منزلي إذا لزم الأمر.
  • التواصل مع الطلاب بشأن كيفية إرسال الواجبات المنزلية
  • وضع درجات للواجبات المنزلية.

ويمكن للمعلّمين استخدام هذه الاقتراحات بقدر ما يريدون أو بقدر ما يريدون، ويجب عدم التردد في تخصيص أي واجبات منزلية أخرى مناسبة.

إذا كنت تستخدم هذا الدرس التطبيقي بنفسك، يمكنك استخدام هذه الواجبات المنزلية لاختبار معلوماتك.

الإجابة عن هذه الأسئلة

السؤال 1

ما هي فئة فرعية من EditText؟

  • View
  • LinearLayout
  • TextView
  • Button

السؤال 2

أيٌّ من قيم سمات visibility التالية، في حال ضبطها على ملف شخصي، تجعلها تُخفي الملف الشخصي ولا تشغل أي مساحة في التنسيق؟

  • visible
  • Invisible
  • gone
  • hide

السؤال 3

بالنسبة إلى ملفات EditText الشخصية، من غير المفيد تقديم تلميحات لأنّ ذلك قد يؤدي إلى تشوش في حقل الإدخال. صحيح أم خطأ؟

  • صحيح
  • خطأ

السؤال 4

أي من العبارات التالية صحيحة حول Button من المشاهدات؟

  • الملف الشخصي Button هو مجموعة ملفات شخصية.
  • يمكنك الحصول على Button مشاهدة واحدة فقط لكل شاشة.
  • Button من الملفات القابلة للنقر، وعند النقر، ينفذ مستمع النقر المرفق إجراءً.
  • Button هو امتداد لـ ImageView.

بدء الدرس التالي: 2.3: التنسيق المحدود باستخدام محرر التنسيق

وللحصول على روابط إلى دروس تطبيقية أخرى حول الترميز في هذه الدورة التدريبية، يُرجى الاطّلاع على الصفحة المقصودة لتطبيق الدروس التطبيقية حول الترميز Kotlin Fundamentals.