کتاب آشپزی صفحه نمایش بزرگ

اندروید تمام مواد لازم را برای برنامه های پنج ستاره با صفحه نمایش بزرگ فراهم می کند. دستور العمل های موجود در این کتاب آشپزی مواد اولیه انتخابی را برای حل مشکلات توسعه خاص انتخاب و ترکیب می کنند. هر دستور غذا شامل بهترین شیوه‌ها، نمونه‌های کد با کیفیت و دستورالعمل‌های گام به گام است که به شما کمک می‌کند تا به یک سرآشپز برتر صفحه‌نمایش بزرگ تبدیل شوید.

رتبه بندی ستاره ها

دستور العمل ها بر اساس میزان هماهنگی آنها با دستورالعمل های کیفیت برنامه های صفحه نمایش بزرگ رتبه بندی شده است.

امتیاز پنج ستاره مطابق با معیارهای سطح 1، صفحه نمایش بزرگ متمایز
رتبه چهار ستاره مطابق با معیارهای سطح 2، صفحه نمایش بزرگ بهینه شده است
رتبه سه ستاره مطابق با معیارهای سطح 3، صفحه نمایش بزرگ آماده است
امتیاز دو ستاره برخی از قابلیت‌های صفحه نمایش بزرگ را ارائه می‌کند، اما از دستورالعمل‌های کیفیت برنامه صفحه نمایش بزرگ کوتاهی می‌کند
امتیاز یک ستاره نیازهای یک مورد خاص را برآورده می کند، اما به درستی از صفحه نمایش بزرگ پشتیبانی نمی کند

پشتیبانی از دوربین Chromebook

رتبه سه ستاره

در Google Play توسط کاربران Chromebook مورد توجه قرار بگیرید.

اگر برنامه دوربین شما فقط با ویژگی‌های اولیه دوربین کار می‌کند، به فروشگاه‌های برنامه اجازه ندهید که کاربران Chromebook را از نصب برنامه جلوگیری کنند، فقط به این دلیل که شما سهواً ویژگی‌های پیشرفته دوربین موجود در تلفن‌های رده بالا را مشخص کرده‌اید.

کروم‌بوک‌ها دارای یک دوربین جلو (رو به کاربر) داخلی هستند که برای کنفرانس ویدیویی، عکس‌های فوری و سایر برنامه‌ها به خوبی کار می‌کند. اما همه کروم‌بوک‌ها دوربین پشتی (جهانی) ندارند و اکثر دوربین‌های رو به کاربر در کروم‌بوک‌ها از فوکوس خودکار یا فلاش پشتیبانی نمی‌کنند.

بهترین شیوه ها

برنامه‌های دوربین همه کاره از همه دستگاه‌ها بدون در نظر گرفتن پیکربندی دوربین پشتیبانی می‌کنند - دستگاه‌هایی با دوربین جلو، دوربین پشت، دوربین‌های خارجی متصل به USB.

برای اطمینان از اینکه فروشگاه‌های برنامه‌ها برنامه شما را برای بیشترین تعداد دستگاه در دسترس قرار می‌دهند، همیشه همه ویژگی‌های دوربین استفاده شده توسط برنامه‌تان را اعلام کنید و صریحاً مشخص کنید که آیا این ویژگی‌ها مورد نیاز است یا خیر.

مواد تشکیل دهنده

  • مجوز CAMERA : به برنامه شما امکان دسترسی به دوربین های دستگاه را می دهد
  • عنصر مانیفست <uses-feature> : به فروشگاه های برنامه از ویژگی های استفاده شده توسط برنامه شما اطلاع می دهد
  • ویژگی required : به فروشگاه‌های برنامه نشان می‌دهد که آیا برنامه شما می‌تواند بدون یک ویژگی مشخص کار کند یا خیر

مراحل

خلاصه

مجوز CAMERA را اعلام کنید. ویژگی های دوربین را که پشتیبانی اولیه دوربین را ارائه می دهند، اعلام کنید. مشخص کنید که آیا هر ویژگی مورد نیاز است یا خیر.

1. مجوز CAMERA را اعلام کنید

مجوز زیر را به مانیفست برنامه اضافه کنید:

<uses-permission android:name="android.permission.CAMERA" />
2. ویژگی های اصلی دوربین را اعلام کنید

ویژگی های زیر را به مانیفست برنامه اضافه کنید:

<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false" />
3. مشخص کنید که آیا هر ویژگی مورد نیاز است یا خیر

android:required="false" را برای ویژگی android.hardware.camera.any تنظیم کنید تا دستگاه‌هایی که دارای هر نوع دوربین داخلی یا خارجی هستند یا اصلاً دوربین ندارند، به برنامه شما دسترسی داشته باشند.

برای سایر ویژگی‌ها، android:required="false" را تنظیم کنید تا مطمئن شوید دستگاه‌هایی مانند Chromebook که دوربین پشتی، فوکوس خودکار یا فلاش ندارند، می‌توانند به برنامه شما در فروشگاه‌های برنامه دسترسی داشته باشند.

نتایج

کاربران Chromebook می‌توانند برنامه شما را از Google Play و سایر فروشگاه‌های برنامه دانلود و نصب کنند. و دستگاه‌هایی که از دوربین با ویژگی‌های کامل پشتیبانی می‌کنند، مانند تلفن‌ها، در عملکرد دوربین خود محدودیتی نخواهند داشت.

با تنظیم صریح ویژگی‌های دوربین پشتیبانی‌شده توسط برنامه‌تان و مشخص کردن ویژگی‌های مورد نیاز برنامه، برنامه‌تان را تا حد امکان برای دستگاه‌های زیادی در دسترس قرار داده‌اید.

منابع اضافی

برای اطلاعات بیشتر، ویژگی های سخت افزار دوربین را در مستندات <uses-feature> ببینید.

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

امتیاز دو ستاره

برنامه شما روی تلفن‌هایی که جهت عمودی هستند عالی کار می‌کند، بنابراین برنامه را فقط به حالت عمودی محدود کرده‌اید. اما شما فرصتی برای انجام کارهای بیشتر در صفحه نمایش های بزرگ در جهت افقی می بینید.

چگونه می توانید آن را به هر دو صورت داشته باشید - برنامه را به جهت عمودی در صفحه های کوچک محدود کنید، اما افقی را در صفحه بزرگ فعال کنید؟

بهترین شیوه ها

بهترین برنامه ها به ترجیحات کاربر مانند جهت گیری دستگاه احترام می گذارند.

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

این دستور العمل یک اقدام موقتی است - کمی پشتیبانی از صفحه نمایش بزرگ. از دستور العمل استفاده کنید تا زمانی که بتوانید برنامه خود را بهبود بخشید تا از همه پیکربندی‌های دستگاه پشتیبانی کامل کنید.

مواد تشکیل دهنده

  • screenOrientation : تنظیم مانیفست برنامه که به شما امکان می‌دهد مشخص کنید برنامه شما چگونه به تغییرات جهت‌گیری دستگاه پاسخ می‌دهد.
  • Jetpack WindowManager : مجموعه ای از کتابخانه ها که به شما امکان می دهد اندازه و نسبت ابعاد پنجره برنامه را تعیین کنید. سازگار با API سطح 14
  • Activity#setRequestedOrientation() : روشی که با آن می توانید جهت برنامه را در زمان اجرا تغییر دهید

مراحل

خلاصه

برنامه را فعال کنید تا تغییرات جهت را به طور پیش فرض در مانیفست برنامه مدیریت کند. در زمان اجرا، اندازه پنجره برنامه را تعیین کنید. اگر پنجره برنامه کوچک است، جهت گیری برنامه را با لغو تنظیمات جهت مانیفست محدود کنید.

1. تنظیمات جهت را در مانیفست برنامه مشخص کنید

می‌توانید از اعلام عنصر screenOrientation در مانیفست برنامه اجتناب کنید (در این صورت جهت‌گیری پیش‌فرض روی unspecified است) یا جهت‌گیری صفحه را روی fullUser تنظیم کنید. اگر کاربر چرخش مبتنی بر حسگر را قفل نکرده باشد، برنامه شما از همه جهت‌های دستگاه پشتیبانی می‌کند.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

تفاوت بین استفاده از unspecified و fullUser ظریف اما مهم است. اگر مقدار screenOrientation را اعلام نکنید، سیستم جهت را انتخاب می‌کند و خط‌مشی که سیستم برای تعریف جهت استفاده می‌کند ممکن است از دستگاهی به دستگاه دیگر متفاوت باشد. از سوی دیگر، مشخص کردن fullUser با رفتاری که کاربر برای دستگاه تعریف کرده است مطابقت بیشتری دارد: اگر کاربر چرخش مبتنی بر حسگر را قفل کرده باشد، برنامه از اولویت کاربر پیروی می کند. در غیر این صورت، سیستم هر یک از چهار جهت گیری صفحه نمایش (عمودی، منظره، عمودی معکوس، یا منظره معکوس) را اجازه می دهد. android:screenOrientation ببینید.

2. اندازه صفحه نمایش را تعیین کنید

با تنظیم مانیفست برای پشتیبانی از همه جهت‌های مجاز کاربر، می‌توانید جهت‌گیری برنامه را به صورت برنامه‌نویسی بر اساس اندازه صفحه مشخص کنید.

کتابخانه های Jetpack WindowManager را به فایل build.gradle یا build.gradle.kts ماژول اضافه کنید:

کاتلین

implementation("androidx.window:window:version")
implementation("androidx.window:window-core:version")

شیار

implementation 'androidx.window:window:version'
implementation 'androidx.window:window-core:version'

از روش Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics() برای به دست آوردن اندازه صفحه نمایش دستگاه به عنوان یک شی WindowMetrics استفاده کنید. معیارهای پنجره را می توان با کلاس های اندازه پنجره مقایسه کرد تا تصمیم بگیرد چه زمانی جهت گیری را محدود کند.

کلاس های اندازه ویندوز نقاط شکست بین صفحه های کوچک و بزرگ را ارائه می دهند.

برای تعیین اندازه صفحه از نقاط شکست WindowWidthSizeClass#COMPACT و WindowHeightSizeClass#COMPACT استفاده کنید:

کاتلین

/** Determines whether the device has a compact screen. **/
fun compactScreen() : Boolean {
    val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
    val width = metrics.bounds.width()
    val height = metrics.bounds.height()
    val density = resources.displayMetrics.density
    val windowSizeClass = WindowSizeClass.compute(width/density, height/density)

    return windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT ||
        windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT
}

جاوا

/** Determines whether the device has a compact screen. **/
private boolean compactScreen() {
    WindowMetrics metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this);
    int width = metrics.getBounds().width();
    int height = metrics.getBounds().height();
    float density = getResources().getDisplayMetrics().density;
    WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density);
    return windowSizeClass.getWindowWidthSizeClass() == WindowWidthSizeClass.COMPACT ||
                windowSizeClass.getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT;
}
    توجه:
  • مثال های فوق به عنوان روش های یک فعالیت پیاده سازی می شوند. و بنابراین، فعالیت به this در آرگومان computeMaximumWindowMetrics() ارجاع داده نمی شود.
  • روش computeMaximumWindowMetrics() به جای computeCurrentWindowMetrics() استفاده می شود زیرا برنامه را می توان در حالت چند پنجره ای راه اندازی کرد که تنظیمات جهت صفحه را نادیده می گیرد. هیچ فایده ای برای تعیین اندازه پنجره برنامه و نادیده گرفتن تنظیمات جهت وجود ندارد، مگر اینکه پنجره برنامه کل صفحه دستگاه باشد.

برای دستورالعمل‌های مربوط به اعلام وابستگی‌ها برای در دسترس قرار دادن متد computeMaximumWindowMetrics() در برنامه خود، به WindowManager مراجعه کنید.

3. تنظیمات مانیفست برنامه را لغو کنید

وقتی تشخیص دادید که دستگاه دارای اندازه صفحه نمایش فشرده است، می توانید Activity#setRequestedOrientation() را فراخوانی کنید تا تنظیمات screenOrientation مانیفست را لغو کنید:

کاتلین

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requestedOrientation = if (compactScreen())
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    ...
    // Replace with a known container that you can safely add a
    // view to where the view won't affect the layout and the view
    // won't be replaced.
    val container: ViewGroup = binding.container

    // Add a utility view to the container to hook into
    // View.onConfigurationChanged. This is required for all
    // activities, even those that don't handle configuration
    // changes. You can't use Activity.onConfigurationChanged,
    // since there are situations where that won't be called when
    // the configuration changes. View.onConfigurationChanged is
    // called in those scenarios.
    container.addView(object : View(this) {
        override fun onConfigurationChanged(newConfig: Configuration?) {
            super.onConfigurationChanged(newConfig)
            requestedOrientation = if (compactScreen())
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
                ActivityInfo.SCREEN_ORIENTATION_FULL_USER
        }
    })
}

جاوا

@Override
protected void onCreate(Bundle savedInstance) {
    super.onCreate(savedInstanceState);
    if (compactScreen()) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
    }
    ...
    // Replace with a known container that you can safely add a
    // view to where the view won't affect the layout and the view
    // won't be replaced.
    ViewGroup container = binding.container;

    // Add a utility view to the container to hook into
    // View.onConfigurationChanged. This is required for all
    // activities, even those that don't handle configuration
    // changes. You can't use Activity.onConfigurationChanged,
    // since there are situations where that won't be called when
    // the configuration changes. View.onConfigurationChanged is
    // called in those scenarios.
    container.addView(new View(this) {
        @Override
        protected void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            if (compactScreen()) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
            }
        }
    });
}

با افزودن منطق به متدهای onCreate() و View.onConfigurationChanged() ، می توانید حداکثر معیارهای پنجره را به دست آورید و هر زمان که اندازه فعالیت تغییر کرد یا بین نمایشگرها جابه جا شد، مانند پس از چرخش دستگاه یا زمانی که تنظیم جهت گیری را لغو کنید. یک دستگاه تاشو تا شده یا باز می شود. برای اطلاعات بیشتر در مورد اینکه چه زمانی تغییرات پیکربندی رخ می دهد و چه زمانی باعث ایجاد فعالیت تفریحی می شود، به تغییرات پیکربندی دسته مراجعه کنید.

نتایج

اکنون برنامه شما باید بدون توجه به چرخش دستگاه، در جهت عمودی در صفحه‌های کوچک باقی بماند. در صفحه نمایش های بزرگ، برنامه باید جهت گیری افقی و عمودی را پشتیبانی کند.

منابع اضافی

برای کمک به ارتقای برنامه خود برای پشتیبانی از تمام تنظیمات دستگاه، موارد زیر را ببینید:

پخش رسانه با Spacebar صفحه کلید خارجی متوقف و از سر گرفته می شود

رتبه چهار ستاره

بهینه‌سازی صفحه بزرگ شامل توانایی مدیریت ورودی‌های صفحه‌کلید خارجی، مانند واکنش به فشار دادن Spacebar برای توقف یا ازسرگیری پخش ویدیوها و رسانه‌های دیگر است. این به ویژه برای تبلت‌هایی که اغلب به صفحه‌کلیدهای خارجی متصل می‌شوند و کروم‌بوک‌هایی که معمولاً با صفحه‌کلیدهای خارجی عرضه می‌شوند، اما می‌توانند در حالت تبلت استفاده شوند، مفید است.

وقتی رسانه تنها عنصر پنجره است (مانند پخش ویدیوی تمام صفحه)، به رویدادهای فشار کلید در سطح فعالیت یا در Jetpack Compose در سطح صفحه پاسخ دهید.

بهترین شیوه ها

هر زمان که برنامه شما یک فایل رسانه ای پخش می کند، کاربران باید بتوانند با فشار دادن Spacebar روی صفحه کلید فیزیکی، پخش را متوقف کرده و از سر بگیرند.

مواد تشکیل دهنده

نوشتن

  • onPreviewKeyEvent : Modifier که یک مؤلفه را قادر می‌سازد تا رویدادهای کلیدی سخت‌افزار را هنگامی که آن (یا یکی از فرزندانش) متمرکز است، رهگیری کند.
  • onKeyEvent : مشابه onPreviewKeyEvent ، این Modifier یک مؤلفه را قادر می‌سازد تا رویدادهای کلیدی سخت‌افزار را هنگامی که آن (یا یکی از فرزندانش) متمرکز است، رهگیری کند.

بازدیدها

  • onKeyUp() : زمانی فراخوانی می شود که یک کلید آزاد می شود و توسط یک view در یک فعالیت کنترل نمی شود.

مراحل

خلاصه

برنامه‌ها و برنامه‌های مبتنی بر نمایش مبتنی بر Jetpack Compose به فشردن کلیدهای صفحه‌کلید به روش‌های مشابهی پاسخ می‌دهند: برنامه باید به رویدادهای فشار کلید گوش دهد، رویدادها را فیلتر کند و به فشارهای کلید انتخاب‌شده مانند فشار کلید Spacebar پاسخ دهد.

1. به رویدادهای صفحه کلید گوش دهید

بازدیدها

در یک فعالیت در برنامه خود، روش onKeyUp() را لغو کنید:

کاتلین

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    ...
}

جاوا

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    ...
}

این روش هر بار که یک کلید فشار داده می‌شود فراخوانی می‌شود، بنابراین برای هر زدن کلید دقیقاً یک بار شلیک می‌شود.

نوشتن

با Jetpack Compose، می‌توانید از onPreviewKeyEvent یا onKeyEvent در صفحه‌ای که ضربه زدن به کلید را مدیریت می‌کند، استفاده کنید:

Column(modifier = Modifier.onPreviewKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp) {
        ...
    }
    ...
})

یا

Column(modifier = Modifier.onKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp) {
        ...
    }
    ...
})

2. فشارهای Spacebar را فیلتر کنید

در متد onKeyUp() یا Compose onPreviewKeyEvent و onKeyEvent متدهای اصلاح‌کننده، KeyEvent.KEYCODE_SPACE را فیلتر کنید تا رویداد صحیح به مؤلفه رسانه شما ارسال شود:

بازدیدها

کاتلین

if (keyCode == KeyEvent.KEYCODE_SPACE) {
    togglePlayback()
    return true
}
return false

جاوا

if (keyCode == KeyEvent.KEYCODE_SPACE) {
    togglePlayback();
    return true;
}
return false;

نوشتن

Column(modifier = Modifier.onPreviewKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
        ...
    }
    ...
})

یا

Column(modifier = Modifier.onKeyEvent { event ->
    if (event.type == KeyEventType.KeyUp && event.key == Key.Spacebar) {
        ...
    }
    ...
})

نتایج

برنامه شما اکنون می‌تواند به فشار دادن کلید Spacebar برای توقف و ازسرگیری یک ویدیو یا رسانه دیگر پاسخ دهد.

منابع اضافی

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

رد کف دست قلم

امتیاز پنج ستاره

قلم می تواند یک ابزار فوق العاده سازنده و خلاقانه در صفحه نمایش های بزرگ باشد. اما زمانی که کاربران با استفاده از قلم با یک برنامه طراحی می‌کنند، می‌نویسند یا با آن تعامل می‌کنند، گاهی اوقات صفحه را با کف دست لمس می‌کنند. قبل از اینکه سیستم رویداد را به‌عنوان لمس تصادفی کف دست تشخیص دهد و آن را رد کند، می‌توان رویداد لمسی را به برنامه شما گزارش داد.

بهترین شیوه ها

برنامه شما باید رویدادهای لمسی خارجی را شناسایی کند و آنها را نادیده بگیرد. Android لمس کف دست را با ارسال یک شی MotionEvent لغو می کند. شی را برای ACTION_CANCEL یا ACTION_POINTER_UP و FLAG_CANCELED بررسی کنید تا مشخص شود که آیا حرکت ناشی از لمس کف دست را رد کنید یا خیر.

مواد تشکیل دهنده

  • MotionEvent : رویدادهای لمسی و حرکتی را نشان می دهد. حاوی اطلاعات لازم برای تعیین اینکه آیا یک رویداد باید نادیده گرفته شود یا خیر.
  • OnTouchListener#onTouch() : اشیاء MotionEvent دریافت می کند.
  • MotionEvent#getActionMasked() : عمل مرتبط با یک رویداد حرکتی را برمی‌گرداند.
  • ACTION_CANCEL : ثابت MotionEvent که نشان می‌دهد یک حرکت باید لغو شود.
  • ACTION_POINTER_UP : ثابت MotionEvent که نشان می‌دهد نشانگر دیگری غیر از اولین نشانگر بالا رفته است (یعنی تماس با صفحه دستگاه را قطع کرده است).
  • FLAG_CANCELED : ثابت MotionEvent که نشان می‌دهد بالا رفتن نشانگر باعث یک رویداد لمسی غیرعمدی شده است. به رویدادهای ACTION_POINTER_UP و ACTION_CANCEL در Android 13 (سطح API 33) و بالاتر اضافه شد.

مراحل

خلاصه

اشیاء MotionEvent ارسال شده به برنامه شما را بررسی کنید. از API های MotionEvent برای تعیین ویژگی های رویداد استفاده کنید:

  • رویدادهای تک اشاره ایACTION_CANCEL را بررسی کنید. در Android نسخه 13 و بالاتر، FLAG_CANCELED را نیز بررسی کنید.
  • رویدادهای چند نشانگر — در Android نسخه 13 و بالاتر، ACTION_POINTER_UP و FLAG_CANCELED را بررسی کنید.

به رویدادهای ACTION_CANCEL و ACTION_POINTER_UP / FLAG_CANCELED پاسخ دهید.

1. اشیاء رویداد حرکتی را بدست آورید

یک OnTouchListener به برنامه خود اضافه کنید:

کاتلین

val myView = findViewById<View>(R.id.myView).apply {
    setOnTouchListener { view, event ->
        // Process motion event.
    }
}

جاوا

View myView = findViewById(R.id.myView);
myView.setOnTouchListener( (view, event) -> {
    // Process motion event.
});
2. عمل رویداد و پرچم ها را تعیین کنید

ACTION_CANCEL را بررسی کنید، که نشان‌دهنده یک رویداد تک نقطه‌ای در همه سطوح API است. در Android 13 و بالاتر، ACTION_POINTER_UP برای FLAG_CANCELED.

کاتلین

val myView = findViewById<View>(R.id.myView).apply {
    setOnTouchListener { view, event ->
        when (event.actionMasked) {
            MotionEvent.ACTION_CANCEL -> {
                //Process canceled single-pointer motion event for all SDK versions.
            }
            MotionEvent.ACTION_POINTER_UP -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
                   (event.flags and MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) {
                    //Process canceled multi-pointer motion event for Android 13 and higher.
                }
            }
        }
        true
    }
}

جاوا

View myView = findViewById(R.id.myView);
myView.setOnTouchListener( (view, event) -> {
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_CANCEL:
            // Process canceled single-pointer motion event for all SDK versions.
        case MotionEvent.ACTION_UP:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
               (event.getFlags() & MotionEvent.FLAG_CANCELED) == MotionEvent.FLAG_CANCELED) {
                //Process canceled multi-pointer motion event for Android 13 and higher.
            }
    }
    return true;
});
3. ژست را لغو کنید

وقتی لمس کف دست را تشخیص دادید، می‌توانید جلوه‌های ژست روی صفحه را لغو کنید.

برنامه شما باید تاریخچه ای از اقدامات کاربر داشته باشد تا بتوان ورودی های ناخواسته مانند لمس کف دست را لغو کرد. به عنوان مثال به اجرای یک برنامه طراحی اولیه در تقویت پشتیبانی قلم در یک کد برنامه Android مراجعه کنید.

نتایج

برنامه شما اکنون می‌تواند لمس کف دست را برای رویدادهای چند اشاره‌گر در Android 13 و سطوح API بالاتر و رویدادهای تک اشاره‌ای در همه سطوح API شناسایی و رد کند.

منابع اضافی

برای اطلاعات بیشتر به ادامه مطلب مراجعه کنید:

مدیریت حالت WebView

رتبه سه ستاره

WebView یک مؤلفه متداول است که یک سیستم پیشرفته برای مدیریت حالت ارائه می دهد. یک WebView باید وضعیت خود را حفظ کند و موقعیت خود را در سراسر تغییرات پیکربندی حرکت دهد. وقتی کاربر دستگاه را می‌چرخاند یا یک تلفن تاشو باز می‌کند، WebView می‌تواند موقعیت اسکرول را از دست بدهد، که کاربر را مجبور می‌کند دوباره از بالای WebView به موقعیت اسکرول قبلی حرکت کند.

بهترین شیوه ها

تعداد دفعاتی که یک WebView دوباره ایجاد می شود را به حداقل برسانید. WebView در مدیریت وضعیت خود خوب است و می توانید با مدیریت هر چه بیشتر تغییرات پیکربندی، از این کیفیت استفاده کنید. برنامه شما باید تغییرات پیکربندی را انجام دهد زیرا Activity recreation (روش سیستم برای مدیریت تغییرات پیکربندی) WebView را نیز بازسازی می کند که باعث می شود WebView حالت خود را از دست بدهد.

مواد تشکیل دهنده

  • android:configChanges : ویژگی عنصر <activity> مانیفست. تغییرات پیکربندی انجام شده توسط فعالیت را فهرست می کند.
  • View#invalidate() : روشی که باعث می‌شود یک view دوباره ترسیم شود. توسط WebView به ارث رسیده است.

مراحل

خلاصه

برای ذخیره وضعیت WebView ، تا آنجا که ممکن است از بازآفرینی Activity اجتناب کنید و سپس اجازه دهید WebView باطل شود تا بتواند با حفظ حالت خود اندازه آن را تغییر دهد.

1. تغییرات پیکربندی را به فایل AndroidManifest.xml برنامه خود اضافه کنید

با مشخص کردن تغییرات پیکربندی که توسط برنامه شما (به جای سیستم) انجام می شود، از فعالیت تفریحی خودداری کنید:

<activity
  android:name=".MyActivity"
  android:configChanges="screenLayout|orientation|screenSize
      |keyboard|keyboardHidden|smallestScreenSize" />

2. هر زمان که برنامه شما تغییری در پیکربندی دریافت کرد، WebView باطل کنید

کاتلین

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    webView.invalidate()
}

جاوا

@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    webview.invalidate();
}

این مرحله فقط برای سیستم view اعمال می شود، زیرا Jetpack Compose برای تغییر اندازه عناصر Composable به درستی نیازی به بی اعتبار کردن چیزی ندارد. با این حال، Compose اغلب اگر به درستی مدیریت نشود، یک WebView را دوباره ایجاد می کند. برای ذخیره و بازیابی حالت WebView در برنامه‌های Compose خود از بسته‌بندی Accompanist WebView استفاده کنید.

نتایج

اجزای WebView برنامه شما اکنون وضعیت خود را حفظ می‌کنند و موقعیت خود را در چندین تغییر پیکربندی، از تغییر اندازه گرفته تا تغییر جهت، تا کردن و باز کردن، حفظ می‌کنند.

منابع اضافی

برای کسب اطلاعات بیشتر در مورد تغییرات پیکربندی و نحوه مدیریت آنها، به کنترل تغییرات پیکربندی مراجعه کنید.

مدیریت حالت RecyclerView

رتبه سه ستاره

RecyclerView می تواند حجم زیادی از داده ها را با استفاده از حداقل منابع گرافیکی نمایش دهد. همانطور که یک RecyclerView در لیست موارد خود پیمایش می کند، RecyclerView از نمونه های View مواردی که از صفحه اسکرول شده اند مجددا استفاده می کند تا آیتم های جدیدی را هنگام حرکت روی صفحه ایجاد کند. اما تغییرات پیکربندی، مانند چرخش دستگاه، می‌تواند وضعیت RecyclerView را بازنشانی کند و کاربران را مجبور کند که دوباره به موقعیت قبلی خود در لیست موارد RecyclerView حرکت کنند.

بهترین شیوه ها

RecyclerView باید وضعیت خود - به ویژه موقعیت اسکرول - و وضعیت عناصر لیست خود را در طول تمام تغییرات پیکربندی حفظ کند.

مواد تشکیل دهنده

  • RecyclerView.Adapter#setStateRestorationPolicy() : مشخص می کند که یک RecyclerView.Adapter چگونه وضعیت خود را پس از تغییر پیکربندی بازیابی می کند.
  • ViewModel : حالت را برای یک فعالیت یا قطعه نگه می دارد.

مراحل

خلاصه

سیاست بازیابی حالت RecyclerView.Adapter را برای ذخیره موقعیت اسکرول RecyclerView تنظیم کنید. وضعیت موارد لیست RecyclerView را ذخیره کنید. وضعیت آیتم های لیست را به آداپتور RecyclerView اضافه کنید و هنگامی که آیتم های لیست به ViewHolder متصل می شوند وضعیت را بازیابی کنید.

1. سیاست بازیابی حالت Adapter را فعال کنید

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

کاتلین

class MyAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    init {
        stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
    }
    ...
}

جاوا

class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public Adapter() {
        setStateRestorationPolicy(StateRestorationPolicy.PREVENT_WHEN_EMPTY);
    }
    ...
}

2. وضعیت موارد فهرست حالت را ذخیره کنید

وضعیت موارد پیچیده لیست RecyclerView را ذخیره کنید، مانند مواردی که حاوی عناصر EditText هستند. به عنوان مثال، برای ذخیره وضعیت یک EditText ، یک پاسخ تماس مشابه با کنترل کننده onClick اضافه کنید تا تغییرات متن را ثبت کنید. در پاسخ به تماس، تعریف کنید که چه داده‌هایی ذخیره شوند:

کاتلین

input.addTextChangedListener(
    afterTextChanged = { text ->
        text?.let {
            // Save state here.
        }
    }
)

جاوا

input.addTextChangedListener(new TextWatcher() {

    ...

    @Override
    public void afterTextChanged(Editable s) {
        // Save state here.
    }
});

پاسخ تماس را در Activity یا Fragment خود اعلام کنید. از ViewModel برای ذخیره وضعیت استفاده کنید.

3. وضعیت مورد لیست را به Adapter اضافه کنید

وضعیت موارد لیست را به RecyclerView.Adapter خود اضافه کنید. هنگامی که Activity یا Fragment میزبان شما ایجاد می شود، وضعیت مورد را به سازنده آداپتور منتقل کنید:

کاتلین

val adapter = MyAdapter(items, viewModel.retrieveState())

جاوا

MyAdapter adapter = new MyAdapter(items, viewModel.retrieveState());

4. وضعیت مورد لیست را در ViewHolder آداپتور بازیابی کنید

در RecyclerView.Adapter ، هنگامی که یک ViewHolder به یک آیتم متصل می کنید، وضعیت مورد را بازیابی کنید:

کاتلین

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    ...
    val item = items[position]
    val state = states.firstOrNull { it.item == item }

    if (state != null) {
        holder.restore(state)
    }
}

جاوا

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    ...
    Item item = items[position];
    Arrays.stream(states).filter(state -> state.item == item)
        .findFirst()
        .ifPresent(state -> holder.restore(state));
}

نتایج

RecyclerView شما اکنون می تواند موقعیت اسکرول خود و وضعیت هر مورد در لیست RecyclerView را بازیابی کند.

منابع اضافی

مدیریت صفحه کلید قابل جدا شدن

رتبه سه ستاره

پشتیبانی از صفحه کلیدهای جداشدنی به حداکثر بهره وری کاربر در دستگاه های صفحه نمایش بزرگ کمک می کند. هر بار که صفحه‌کلید به دستگاهی متصل می‌شود یا از آن جدا می‌شود، Android باعث تغییر پیکربندی می‌شود که می‌تواند باعث از بین رفتن حالت رابط کاربر شود. برنامه شما می‌تواند وضعیت خود را ذخیره و بازیابی کند ، به سیستم اجازه می‌دهد تا فعالیت‌های تفریحی را مدیریت کند، یا بازآفرینی فعالیت را برای تغییرات پیکربندی صفحه‌کلید محدود کند . در همه موارد تمام داده های مربوط به صفحه کلید در یک شیء Configuration ذخیره می شود. فیلدهای keyboard و keyboardHidden شیء پیکربندی حاوی اطلاعاتی در مورد نوع صفحه کلید و در دسترس بودن آن است.

بهترین شیوه ها

برنامه‌های بهینه‌سازی شده برای صفحه‌نمایش‌های بزرگ از هر نوع دستگاه ورودی، از صفحه‌کلیدهای نرم‌افزاری و سخت‌افزاری گرفته تا قلم، ماوس، ترک‌پد و سایر دستگاه‌های جانبی پشتیبانی می‌کنند.

پشتیبانی از صفحه‌کلیدهای خارجی شامل تغییرات پیکربندی است که می‌توانید آن‌ها را به دو روش مدیریت کنید:

  1. به سیستم اجازه دهید فعالیت در حال اجرا را دوباره ایجاد کند و شما مراقب وضعیت برنامه خود باشید.
  2. تغییر پیکربندی را خودتان مدیریت کنید (فعالیت دوباره ایجاد نخواهد شد):
    • تمام مقادیر پیکربندی مرتبط با صفحه کلید را اعلام کنید
    • یک کنترل کننده تغییر پیکربندی ایجاد کنید

برنامه‌های بهره‌وری، که اغلب به کنترل دقیق رابط کاربری برای ورود متن و سایر ورودی‌ها نیاز دارند، می‌توانند از رویکرد انجام خودت برای مدیریت تغییرات پیکربندی بهره ببرند.

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

از آنجایی که تنها راه قابل اعتماد برای گوش دادن به تغییرات پیکربندی، نادیده گرفتن روش onConfigurationChanged() یک view است، می توانید یک نمونه View جدید به فعالیت برنامه خود اضافه کنید و در کنترلر onConfigurationChanged() view به تغییرات پیکربندی ناشی از بودن صفحه کلید پاسخ دهید. متصل یا جدا شده

مواد تشکیل دهنده

  • android:configChanges : ویژگی عنصر <activity> مانیفست برنامه. تغییرات پیکربندی که برنامه مدیریت می کند به سیستم اطلاع می دهد.
  • View#onConfigurationChanged() : روشی که به انتشار یک پیکربندی برنامه جدید واکنش نشان می دهد.

مراحل

خلاصه

ویژگی configChanges را اعلام کنید و مقادیر مربوط به صفحه کلید را اضافه کنید. یک View به سلسله مراتب نمای فعالیت اضافه کنید و به تغییرات پیکربندی گوش دهید.

1. ویژگی configChanges را اعلام کنید

با افزودن مقادیر keyboard|keyboardHidden به لیست تغییرات پیکربندی مدیریت شده قبلی، عنصر <activity> را در مانیفست برنامه به‌روزرسانی کنید:

<activity
            android:configChanges="...|keyboard|keyboardHidden">

2. یک نمای خالی به سلسله مراتب view اضافه کنید

یک نمای جدید اعلام کنید و کد کنترل کننده خود را در متد onConfigurationChanged() view اضافه کنید:

کاتلین

val v = object : View(this) {
  override fun onConfigurationChanged(newConfig: Configuration?) {
    super.onConfigurationChanged(newConfig)
    // Handler code here.
  }
}

جاوا

View v = new View(this) {
    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Handler code here.
    }
};

نتایج

اکنون برنامه شما به صفحه کلید خارجی متصل یا جدا شده بدون ایجاد مجدد فعالیت فعلی پاسخ می دهد.

منابع اضافی

برای یادگیری نحوه ذخیره وضعیت رابط کاربری برنامه خود در طول تغییرات پیکربندی مانند پیوست یا جدا شدن صفحه کلید، به ذخیره حالت‌های رابط کاربری مراجعه کنید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}