Event Handling ؛ کنترل رویدادها در اندروید

در این فصل با نحوه ارتباط عناصر داخل اکتیویتی مانند دکمه ها با کلاس جاوا و کنترل رویدادها و تعدادی موارد تکمیلی آشنا می شویم که شامل مباحث زیر می باشد :

  • آشنایی با فایل AndroidManifest.xml
  • آشنایی با انواع کامپوننت ها
  • معرفی رویدادها در برنامه نویسی
  • معرفی کنترل کننده ها و شنونده های رویدادها
  • نحوه کنترل رویداد عناصر موجود در اکتیویتی
  • جلوگیری از تخریب اکتیویتی هنگام چرخش صفحه نمایش و دیوایس
  • آشنایی با تگ ScrollView برای اضافه کردن قابلیت اسکرول به اکتیویتی

این فصل در ۴۰ صفحه تهیه شده که در ادامه می توانید چند صفحه ابتدایی را مشاهده نمایید :

به نام خدا. قبل از شروع مبحث کنترل رویدادها به معرفی یکی از مهم ترین بخش های اپلیکیشن اندرویدی می پردازیم :
فایل AndroidManifest.xml :
به طور کلی، اطلاعات اصلی و مهم اپلیکیشن درون این فایل نگهداری می شود. یک پروژه جدید با نام Events و API9 ساختیم. از مسیر manifests فایل AndroidManifest.xml را باز می کنیم :

AndroidManifest.xml

در خط ۳ نام پکیج قرار گرفته است.خطوط ۷ و ۸ به ترتیب مربوط به آیکون و نام اپ ما می باشد که در لیست اپلیکیشن های نصب شده روی دیوایس نمایش داده می شود. در خط ۱۱ مشاهده می کنید اکتیویتی MainActivity تعریف شده. به همین صورت هر اکتیویتی که بخواهیم به پروژه اضافه کنیم باید درون مانیفست نیز اضافه شود. اطلاعات دیگر مانند تِم (قالب) اپلیکیشن، مجوزها، کامپوننت ها و … همگی درون این فایل تعریف می شوند.
Theme (تم) مربوط به ظاهر برنامه می شود که در مباحث آینده به آن می پردازیم.
از مجوزها می توانیم به مجوز دسترسی اپلیکیشن به دوربین، مخاطبین (دفترچه تلفن)، میکروفون، ارسال SMS، و … اشاره کرد. حتما هنگام نصب یک اپلیکیشن روی گوشی اندرویدی خود، با لیستی شامل Permission های مختلف مواجه شده اید که سیستم عامل از شما می خواهد با آگاهی از دسترسی هایی که این اپ می تواند روی تلفن هوشمند شما داشته باشد اقدام به نصب نمائید. برای مثال شما قصد ساخت اپلیکیشنی دارید که کاربر توسط دوربین تلفن یا تبلت خود عکس بگیرد و به ویرایش آن بپردازد. برای اینکه اپ شما به دوربین دیوایس کاربر دسترسی داشته باشد باید مجوز آن را درون مانیفست اضافه کنید.
کامپوننت ها هم شامل Activity ها، Service ها، Broadcast Receiver ها (دریافت کننده اطلاعات) و Content Provider ها (تامین کننده محتوا) هستند.
با اکتیویتی قبلا آشنا شدیم. Service ها مربوط به پردازش های اپلیکیشن هستند.
Broadcast Receiver پل ارتباطی بین اپلیکیشن و سیستم عامل و سایر اپلیکیشن هاست.
Content Provider هم مربوط به مدیریت داده ها می باشد.
هدف از معرفی کامپوننت ها آشنایی مختصر با این موارد بود. در ادامه آموزشها مفصل به معرفی آنها می پردازیم.
توضیحات بالا اهمیت فایل مانیفست را می رساند و روشن است که سیستم عامل اندروید اطلاعات مورد نیاز خود درباره اپلیکیشن را از این فایل می گیرد.

رویداد یا Event چیست
همانطور که در پاراگراف قبل عنوان شد، اکتیویتی ها یکی از کامپوننت های سیستم عامل اندروید هستند. رویدادها روشی است جهت جمع آوری اطلاعات درباره نحوه تعامل کاربر با کامپوننت های اپلیکیشن. اندروید رویدادها را به صورت صف FIFO (First in First out به این معنی که هر رویدادی که زودتر اتفاق بیفتد زودتر پردازش می شود) نگهداری و پردازش می کند.
در مدیریت رویدادها با سه مفهوم اساسی سروکار داریم :
Event Listeners ، Event Listener Registeration و در نهایت Event Handlers.
واژه Listener به معنی شنونده بوده بنابراین Event Listeners را می توان شنونده رویدادها ترجمه کرد.به طور خلاصه کاربر وقتی روی یک view (به عنوان مثال یک دکمه) کلیک می کند، این رویداد توسط سیستم عامل شنود می شود.توسط Event Listener Registeration رویداد ثبت و توسط Event Handlers کنترل می شود. در صفحه
https://developer.android.com/guide/topics/ui/ui-events.html
انواع رویدادهای اندروید لیست شده که به معرفی آنها می پردازیم :

کنترل کننده رویداد شنونده رویداد
onClick() View.OnClickListener()

متد زمانی اجرا می شود که کاربر یکی از ویجت های موجود در صفحه نمایش مانند دکمه، تصویر، متن و … را لمس کند

onLongClick() View.OnLongClickListener()

متد مشابه متد قبل بوده با این تفاوت که عمل لمس کردن ویجت مدنظر باید یک ثانیه و یا بیشتر طول بکشد.

onFocusChange() View.OnFocusChangeListener()

متد زمانی اجرا می شود که عمل فوکوس (تمرکز) از روی ویجت موردنظر برداشته شود. یعنی ویجتی که توسط کاربر لمس شده، رها شود.

onKey() View.OnKeyListener()

متد زمانی اجرا می شود که روی ویجت عمل فوکوس انجام شده و یا یک کلید سخت افزاری فشرده شود.

onTouch() View.OnTouchListener()

متد زمانی اجرا می شود که کاربر هر عملی را بر روی صفحه نمایش انجام دهد مانند لمس دکمه یا رها کردن آن، لمس قسمتی از صفحه و …

onCreateContextMenu() View.OnCreateContextMenuListener()

این متد زمانی اجرا می شود که یک منو ساخته شده.

خب! حالا وقت آن رسیده که مفاهیم را در قالب پروژه ای با عنوان شمارنده بررسی کنیم.

ابتدا یک پروژه جدید با نام دلخواه می سازیم. ما نام Counter را برای پروژه خودمان انتخاب کردیم :

ساخت پروژه اندروید

تعیین Minimum SDK

پس از انتشار نسخه ۲٫۲ اندروید استودیو، حداقل API یی که در لیست Minimum SDK قرار داده شده API 9 می باشد و به این معنی است که تقریبا صددرصد دیوایس های اندرویدی از API 9 به بالا هستند و نیازی به ساخت اپلیکیشن برای نسخه های پایین تر نیست. ما هم به تصمیم گوگل احترام گذاشته، API 9 را انتخاب می کنیم. همچنین از چند نسخه اخیر، گزینه Empty Activity جایگزین Blank Activity شده که همین را انتخاب می کنیم.

Empty Activity

مشخصات اکتیویتی

گزینه Backwards Compatibility (AppCompat) مربوط به استفاده از کتابخانه AppCompat داخل پروژه می باشد که در فصل قبل آشنا شدیم. در نسخه ۲٫۲ امکانات جدیدی به اندروید استودیو اضافه شده که یکی از آنها Layout Inspector حرفه ای می باشد که در تصویر زیر مشاهده می کنید :

اضافه شدن Layout Inspector

البته با استفاده از گزینه های بالا – سمت چپ می توان قسمت BluePrint را فعال یا غیرفعال کرد. متن Hello World پیش فرض را حذف و با کلیک روی صفحه پیش نمایش، قسمت Properties مربوط به اکتیویتی ظاهر شده که یک بک گراند به دلخواه انتخاب یا کد رنگ Hexadecimal آن را وارد می کنیم.

تغییر بک گراند اکتیویتی

همچنین اکتیویتی را از RelativeLayout به LinearLayout تغییر دادیم تا اجزایی که به اکتیویتی اضافه می کنیم زیر یکدیگر قرار بگیرند (اضافه کردن خاصیت orientation یادتان نرود). در ابتدا پروژه ما شامل دو TextView و دو Button می باشد که از دکمه ها برای اضافه و کم کردن عدد و TextView برای نمایش عبارت “شماره” و خروجی int استفاده می شود.

اضافه کردن view ها به اکتیویتی

در اینجا نیازی به نوشتن دستی کد xml ویجت ها ندیدیم و به راحتی از پالت سمت چپ، ویجت ها را کشیده و روی صفحه پیش نمایش قرار دادیم. TextView1 را به “شماره” تغییر می دهیم.TextView دوم بناست برای نمایش عدد خروجی (int) استفاده شود که در ابتدا باید عدد صفر را نمایش دهیم.
کد activity_main.xml به این صورت شد :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="ir.android_studio.counter.MainActivity"
    android:background="@color/colorPrimary">

    <TextView
        android:text="@string/top_txt"
        android:textSize="30sp"
        android:textAlignment="center"
        android:textColor="@color/t_top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <TextView
        android:text="@string/result"
        android:textSize="70sp"
        android:textAlignment="center"
        android:textColor="@color/t_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/resultText" />

    <Button
        android:text="@string/plus"
        android:textSize="25sp"
        android:background="@color/button_bg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button_plus" />

    <Button
        android:text="@string/minus"
        android:textSize="25sp"
        android:background="@color/button_bg"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button_minus" />

</LinearLayout>

کد فایل رنگها (colors.xml) :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#dedede</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="t_top">#665454</color>
    <color name="t_result">#de0707</color>
    <color name="button_bg">#7bc11a</color>
</resources>

توضیح : این فایل مشابه strings.xml بوده به اینصورت که با تعریف رنگها داخل این فایل، در کل پروژه می توانیم به رنگها دسترسی داشته که به بهینه شدن اپ ما کمک می کند.
کد فایل dimens.xml :

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>

اندروید استودیو به صورت پیش فرض از این فایل برای تعریف فاصله اکتیویتی از ۴ جهت صفحه نمایش استفاده کرده. مزیت استفاده از این فایل به جای تعریف مستقیم واحدها درون کد اصلی، مشابه String ها و رنگ ها می باشد. استفاده مستقیم رشته ها، رنگ ها و واحدهای اندازه گیری درون کد اصلی با عنوان Hardcode شناخته می شود، به معنی کدِ سخت. که اندروید استودیو نیز از شما ایراد گرفته و پیشنهاد می کند استفاده از Hardcode را به کمترین میزان و در بهترین حالت به صفر برسانید تا هم برنامه بهینه تری داشته باشید هم اینکه هرگاه نیاز به ایجاد یک تغییر جزئی در یک یا چند قسمت از پروژه را داشتید، به سرعت بتوانید تغییر دلخواه را انجام دهید. به عنوان مثال در این پروژه ما یک بار رنگ پس زمینه دکمه ها را درون colors.xml تعریف و ۳ بار استفاده کرده ایم. هرگاه بخواهیم پس زمینه دکمه ها را تغییر بدهیم کافیست برای یک بار کد رنگ را جایگزین کد فعلی کنیم. اما در حالت معمول که کد رنگ را درون هر دکمه جداگانه تعریف کرده ایم نیاز به ۳ مرتبه جایگزینی خواهد بود.
توجه : به دلیل اینکه توضیحات کامل در خصوص dimens.xml شامل این فصل آموزشی نمی شود، فعلا واحدها را به صورت هاردکُد استفاده می کنیم.
کد فایل رشته ها (strings.xml) :

<resources>
    <string name="app_name">شمارشگر</string>
    <string name="top_txt">شماره</string>
    <string name="result">0</string>
    <string name="plus">اضافه کن</string>
    <string name="minus">کم کن</string>
</resources>

خروجی :

اجرای پروژه روی شبیه ساز جنی موشین

حالا به سراغ فایل جاوای اکتیویتی یعنی MainActivity.java می رویم. محتوای اولیه این فایل به اینصورت می باشد :

package ir.android_studio.counter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

با توجه به اینکه خروجی کد ما اعداد صحیح هستند، از متغیر int استفاده می کنیم. متغیری از جنس int میسازیم تا مقادیر اعداد صحیح را درون خود ذخیره نماید. داخل کلاس اصلی اکتیویتی متغیر را تعریف می کنیم با یک نام دلخواه :

package ir.android_studio.counter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    int counter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

حالا مقدار پیش فرض یعنی صفر را برای این متغیر درون متد onCreate تعریف می کنیم. ویجتی که با آی دی resultText ساخته بودیم از نوع TextView بود که قرار است وظیفه نمایش عدد را بر عهده بگیرد. پس با استفاده از id بین کد جاوا و بخش ویجت های صفحه ارتباط برقرار می کنیم و تعیین می کنیم عدد خروجی جایگزین عدد پیش فرض یعنی صفر شود :

package ir.android_studio.counter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    int counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        counter = 0;
        TextView Number = (TextView)findViewById(R.id.resultText);
    }
}

مشاهده می کنید counter را برابر عدد صفر قرار دادیم.
خط بعد را بررسی می کنیم : با توجه به اینکه برای نمایش عدد از ویجت TextView استفاده کرده ایم، همین کلاس را نوشته و یک نام دلخواه انتخاب می کنیم که ما Number در نظر گرفتیم. یک مساوی از نوع انتساب قرار داده و سپس برای اینکه به سیستم عامل اعلام کنیم از چه نوع View ای استفاده کرده ایم، نوع آن را مجدد داخل پرانتز می نویسیم (این عمل Casting نام دارد که در آموزشهای جاوا توضیح داده شده). در نهایت و بدون ایجاد فضای خالی، متد findViewById(R.id.resultText) را اضافه می کنیم که مشخص است کار آن ایجاد دسترسی به View ای با آی دی resultText می باشد. R.id دسترسی به Resource ها از طریق id را فراهم می کند. از این به بعد هر خروجی از نوع String که داخل شئ Number بریزیم در این TextView نمایش داده خواهد شد. نوبت به تعریف عملکرد Button ها می رسد. به صورت زیر، از دو دکمه که برای کم و زیاد کردن عدد نمایشگر ساخته ایم دو شئ می سازیم و توسط id آنها به شئ مربوطه هرکدام متصل می کنیم :

package ir.android_studio.counter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    int counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        counter = 0;
        TextView Number = (TextView)findViewById(R.id.resultText);
        Button btn_1 = (Button)findViewById(R.id.button_plus);
        Button btn_2 = (Button)findViewById(R.id.button_minus);
    }
}

همانطور که در آموزش “اکتیویتی” توضیح دادیم، هر یک از این کلاس هایی که استفاده می کنیم قبلا درون سیستم عامل اندروید تعریف شده اند و برای دسترسی به آنها ملزم به import کردن کلاسها به ابتدای کد هستیم. هنگامی که کلاس TextView را می نویسید، اگر لیست باز شد و TextView را از لیست انتخاب کردید، عمل import نیز به صورت خودکار انجام می شود. اما اگر از لیست انتخاب نکردید و کلاس را خودتان تا انتها نوشتید یا به هر علتی کلاس در بالای کد جاوا خودکار import نشد، کافیست روی نام کلاس کلیک کنید تا پیغام مشابه زیر نمایش داده شود که به ما اعلام می کند عمل import را می توانیم با دو کلید alt + enter انجام دهیم :

ایمپورت خودکار کلاس رویدادها

ایمپورت خودکار کلاس رویدادها

توجه : سورس پروژه نیز به همراه فایل آموزش درون پوشه Exercises قرار داده شده است.

جهت مطالعه ادامه آموزش، فایل PDF را دانلود نمائید.

با توجه به اینکه آموزشهای پایه با قیمت ناچیزی برای تامین هزینه های وب سایت و تهیه آموزش های بعدی عرضه می شود، به اشتراک گذاری این فایل با دیگران خلاف اخلاق خواهد بود.

در صورتی که در پرداخت سبد خرید زیر با مشکل مواجه شدید، با مراجعه به این لینک مشخصات خود را به همراه مبلغ ۳۰۰۰ تومان ثبت نمایید.

دانلود فایل آموزشی با فرمت PDF به همراه سورس پروژه
تعداد صفحات : ۴۰
حجم : ۲٫۵ مگابایت
قیمت : ۳۰۰۰ تومان

۰۲ آبان ۱۳۹۵
سوالاتی که مشمول موارد زیر باشد تایید و پاسخ داده نخواهد شد :
۱ : جزء موارد پاسخ داده شده در مطلب "مشکلات و پرسش های رایج" باشد
۲ : سوال قبلا توسط افراد در دیدگاهها مطرح و پاسخ داده شده باشد
۳ : سوال خارج از مبحث آموزشی موجود در این صفحه باشد

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

*

چگونه آموزش های اندروید استودیو را مطالعه کنم؟

مشکلات و پرسش های رایج

معرفی
با انتشار نسخه ۱ اندروید استودیو، گوگل، توسعه دهندگان را به مهاجرت از ایکلیپس به این محیط برنامه نویسی تشویق می کند.
با توجه به اینکه اکثر آموزشهای موجود (به خصوص آموزشهای فارسی) بر پایه محیط Eclipse هستند، تصمیم گرفتیم آموزشهای ویژه برنامه نویسی در محیط Android Studio را به زبان فارسی منتشر نماییم.
آموزشهای پایه در حال تکمیل بوده و در کنار آموزش پایه، مباحث تکمیلی به صورت رایگان منتشر خواهد شد.