มีเลย์เอาต์วิดเจ็ตที่ยืดหยุ่น

หน้านี้อธิบายการปรับแต่งเพื่อปรับขนาดวิดเจ็ตและความยืดหยุ่นที่มากขึ้น เปิดตัวใน Android 12 (API ระดับ 31) และยังบอกรายละเอียดวิธีการ ระบุขนาดของวิดเจ็ต

ใช้ API ที่ปรับปรุงใหม่สำหรับขนาดและเลย์เอาต์ของวิดเจ็ต

ตั้งแต่ Android 12 (API ระดับ 31) เป็นต้นไป คุณจะระบุขนาดที่ละเอียดยิ่งขึ้นได้ และเลย์เอาต์ที่ยืดหยุ่นได้โดยทำดังนี้ ดังที่อธิบายไว้ใน ส่วนต่างๆ ที่ตามมา:

  1. ระบุข้อจำกัดเกี่ยวกับขนาดวิดเจ็ตเพิ่มเติม

  2. การให้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์หรือแบบตรงทั้งหมด

ใน Android เวอร์ชันก่อนหน้า อาจมีช่วงขนาดของ โดยใช้ OPTION_APPWIDGET_MIN_WIDTH OPTION_APPWIDGET_MIN_HEIGHT, OPTION_APPWIDGET_MAX_WIDTH, และ OPTION_APPWIDGET_MAX_HEIGHT เกินขนาด แล้วประเมินขนาดของวิดเจ็ต แต่ตรรกะนั้นใช้ไม่ได้กับกรณีทั้งหมด เท่านั้น สำหรับวิดเจ็ตที่กำหนดเป้าหมายเป็น Android 12 ขึ้นไป เราขอแนะนำ การระบุคำที่ปรับเปลี่ยนตามอุปกรณ์หรือแบบตรงทั้งหมด เลย์เอาต์

ระบุข้อจำกัดเกี่ยวกับขนาดวิดเจ็ตเพิ่มเติม

Android 12 เพิ่ม API เพื่อให้คุณตรวจสอบว่าวิดเจ็ต ปรับขนาดให้พอดีกับอุปกรณ์ต่างๆ ที่มีขนาดหน้าจอแตกต่างกันได้อย่างน่าเชื่อถือ

นอกจาก minWidth ที่มีอยู่แล้ว minHeight, minResizeWidth, และ minResizeHeight ให้ใช้แอตทริบิวต์ appwidget-provider ใหม่ต่อไปนี้

  • targetCellWidth และ targetCellHeight: ระบุขนาดเป้าหมายของวิดเจ็ตเป็นรูปเซลล์ตาราง Launcher ถ้า มีการระบุแอตทริบิวต์เหล่านี้แทน minWidth หรือ minHeight

  • maxResizeWidth และ maxResizeHeight: กำหนดขนาดสูงสุดที่ตัวเรียกใช้งานอนุญาตให้ผู้ใช้ปรับขนาดวิดเจ็ตได้

XML ต่อไปนี้แสดงวิธีใช้แอตทริบิวต์การปรับขนาด

<appwidget-provider
  ...
  android:targetCellWidth="3"
  android:targetCellHeight="2"
  android:maxResizeWidth="250dp"
  android:maxResizeHeight="110dp">
</appwidget-provider>

จัดเตรียมเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์

หากเลย์เอาต์จำเป็นต้องเปลี่ยนตามขนาดของวิดเจ็ต เราขอแนะนำให้ สร้างเลย์เอาต์ชุดเล็กๆ โดยแต่ละเลย์เอาต์ใช้ได้กับขนาดที่แตกต่างกัน หากสิ่งนี้ ไม่สามารถทำได้ อีกทางเลือกหนึ่งคือการจัดหาเลย์เอาต์ตามวิดเจ็ตที่ตรงกันทั้งหมด ขนาดขณะรันไทม์ ตามที่อธิบายไว้ในหน้านี้

ฟีเจอร์นี้ช่วยให้การปรับขนาดราบรื่นขึ้นและระบบโดยรวมดีขึ้น เนื่องจากระบบไม่จำเป็นต้องปลุกแอปทุกครั้ง วิดเจ็ตจะแสดงวิดเจ็ตในขนาดอื่น

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแสดงรายการเลย์เอาต์

Kotlin

override fun onUpdate(...) {
    val smallView = ...
    val tallView = ...
    val wideView = ...

    val viewMapping: Map<SizeF, RemoteViews> = mapOf(
            SizeF(150f, 100f) to smallView,
            SizeF(150f, 200f) to tallView,
            SizeF(215f, 100f) to wideView
    )
    val remoteViews = RemoteViews(viewMapping)

    appWidgetManager.updateAppWidget(id, remoteViews)
}

Java

@Override
public void onUpdate(...) {
    RemoteViews smallView = ...;
    RemoteViews tallView = ...;
    RemoteViews wideView = ...;

    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    viewMapping.put(new SizeF(150f, 100f), smallView);
    viewMapping.put(new SizeF(150f, 200f), tallView);
    viewMapping.put(new SizeF(215f, 100f), wideView);
    RemoteViews remoteViews = new RemoteViews(viewMapping);

    appWidgetManager.updateAppWidget(id, remoteViews);
}

สมมติว่าวิดเจ็ตมีแอตทริบิวต์ต่อไปนี้

<appwidget-provider
    android:minResizeWidth="160dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="200dp">
</appwidget-provider>

ข้อมูลโค้ดที่อยู่ก่อนหน้ามีความหมายดังต่อไปนี้

  • smallView รองรับความละเอียดตั้งแต่ 160 dp (minResizeWidth) × 110 dp (minResizeHeight) ถึง 160dp × 199dp (จุดตัดถัดไปคือ 1dp)
  • tallView รองรับตั้งแต่ 160dp × 200dp ถึง 214dp (จุดตัดถัดไป - 1) × 200dp
  • wideView รองรับตั้งแต่ 215dp × 110dp (minResizeHeight) ถึง 250dp (maxResizeWidth) × 200dp (maxResizeHeight)

วิดเจ็ตต้องรองรับขนาดตั้งแต่ minResizeWidth × minResizeHeight ถึง maxResizeWidth × maxResizeHeight ภายในช่วงดังกล่าว คุณสามารถเลือกจุดตัดเพื่อเปลี่ยนเลย์เอาต์ได้

วันที่ ตัวอย่างเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์
รูปที่ 1 ตัวอย่างของเลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์

แสดงเลย์เอาต์ที่แน่นอน

หากไม่สามารถใช้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์ชุดเล็กๆ ให้คุณระบุ รูปแบบต่างๆ ที่ปรับแต่งให้เหมาะกับขนาดที่วิดเจ็ตแสดง นี่คือ ซึ่งโดยทั่วไปแล้วจะมี 2 ขนาดสำหรับโทรศัพท์ (โหมดแนวตั้งและแนวนอน) และ 4 ขนาดสำหรับ อุปกรณ์แบบพับได้

ในการใช้โซลูชันนี้ แอปของคุณต้องทำตามขั้นตอนต่อไปนี้

  1. โอเวอร์โหลด AppWidgetProvider.onAppWidgetOptionsChanged() ซึ่งจะถูกเรียกเมื่อชุดของขนาดมีการเปลี่ยนแปลง

  2. โทร AppWidgetManager.getAppWidgetOptions() ซึ่งแสดงผล Bundle ที่มีขนาด

  3. เข้าถึงคีย์ AppWidgetManager.OPTION_APPWIDGET_SIZES จาก Bundle

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีระบุเลย์เอาต์ที่แน่นอน

Kotlin

override fun onAppWidgetOptionsChanged(
        context: Context,
        appWidgetManager: AppWidgetManager,
        id: Int,
        newOptions: Bundle?
) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions)
    // Get the new sizes.
    val sizes = newOptions?.getParcelableArrayList<SizeF>(
            AppWidgetManager.OPTION_APPWIDGET_SIZES
    )
    // Check that the list of sizes is provided by the launcher.
    if (sizes.isNullOrEmpty()) {
        return
    }
    // Map the sizes to the RemoteViews that you want.
    val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews))
    appWidgetManager.updateAppWidget(id, remoteViews)
}

// Create the RemoteViews for the given size.
private fun createRemoteViews(size: SizeF): RemoteViews { }

Java

@Override
public void onAppWidgetOptionsChanged(
    Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    // Get the new sizes.
    ArrayList<SizeF> sizes =
        newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES);
    // Check that the list of sizes is provided by the launcher.
    if (sizes == null || sizes.isEmpty()) {
      return;
    }
    // Map the sizes to the RemoteViews that you want.
    Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
    for (SizeF size : sizes) {
        viewMapping.put(size, createRemoteViews(size));
    }
    RemoteViews remoteViews = new RemoteViews(viewMapping);
    appWidgetManager.updateAppWidget(id, remoteViews);
}

// Create the RemoteViews for the given size.
private RemoteViews createRemoteViews(SizeF size) { }

กำหนดขนาดสำหรับวิดเจ็ต

วิดเจ็ตแต่ละรายการต้องระบุ targetCellWidth และ targetCellHeight สำหรับอุปกรณ์ ใช้ Android 12 ขึ้นไป หรือ minWidth และ minHeight สําหรับทั้งหมด Android เวอร์ชันต่างๆ - ระบุพื้นที่ขั้นต่ำที่แอปใช้ โดยค่าเริ่มต้น แต่เมื่อผู้ใช้เพิ่มวิดเจ็ตในหน้าจอหลัก ใช้พื้นที่มากกว่าความกว้างและความสูงขั้นต่ำที่คุณระบุ

หน้าจอหลักของ Android จะแสดงข้อมูลพื้นที่ที่ผู้ใช้สามารถใช้งานได้ วางวิดเจ็ตและไอคอน ตารางกริดนี้อาจแตกต่างกันไปตามอุปกรณ์ ตัวอย่างเช่น จำนวนมาก โทรศัพท์มือถือมีตารางกริดขนาด 5x4 ส่วนแท็บเล็ตมีตารางกริดขนาดใหญ่กว่า เมื่อวิดเจ็ต จะถูกยืดออกไปเพื่อให้ครอบคลุมจำนวนเซลล์ต่ำสุด ในแนวนอนและแนวตั้ง จำเป็นต้องมีเพื่อให้เป็นไปตามข้อจำกัด targetCellWidth และ targetCellHeight ในอุปกรณ์ที่ใช้ Android 12 ขึ้นไป หรือข้อจํากัด minWidth และ minHeight เปิดอยู่ อุปกรณ์ที่ใช้ Android 11 (API ระดับ 30) หรือต่ำกว่า

ทั้งความกว้างและความสูงของเซลล์และขนาดของระยะขอบอัตโนมัติที่ใช้ วิดเจ็ตอาจแตกต่างกันไปตามอุปกรณ์ ใช้ตารางต่อไปนี้เพื่อประมาณการคร่าวๆ ขนาดขั้นต่ำของวิดเจ็ตในเครื่องแบบตารางกริด 5x4 โดยทั่วไปโดยพิจารณาจาก จำนวนเซลล์ตารางกริดที่มีการเข้าใช้ที่คุณต้องการ:

จำนวนเซลล์ (กว้าง x สูง) ขนาดที่มีให้เลือกในโหมดแนวตั้ง (dp) ขนาดที่มีในโหมดแนวนอน (dp)
แบบ 1X1 57x102dp 127x51dp
แบบ 2X1 130x102dp 269x51dp
แบบ 3X1 203x102dp 412x51dp
แบบ 4X1 276x102dp 554x51dp
5x1 349x102dp 697x51dp
5x2 349x220dp 697x117dp
5x3 349x337dp 697x184dp
5x4 349x455dp 697x250dp
... ... ...
กว้าง x ม. (73n - 16) x (118 นาที - 16) (142n - 15) x (66 นาที - 15)

ใช้ขนาดเซลล์ในโหมดแนวตั้งเพื่อแจ้งค่าที่คุณระบุสำหรับ แอตทริบิวต์ minWidth, minResizeWidth และ maxResizeWidth ในทำนองเดียวกัน ใช้ขนาดเซลล์ในโหมดแนวนอนเพื่อให้ข้อมูลค่าที่คุณระบุ สำหรับแอตทริบิวต์ minHeight, minResizeHeight และ maxResizeHeight

เนื่องจากโดยทั่วไปแล้วความกว้างของเซลล์จะน้อยกว่าในโหมดแนวตั้ง เมื่อเทียบกับโหมดแนวนอน และในทำนองเดียวกัน ความสูงของเซลล์มักจะ ในโหมดแนวนอนจะมีขนาดเล็กกว่าในโหมดแนวตั้ง

ตัวอย่างเช่น หากคุณต้องการปรับขนาดความกว้างของวิดเจ็ตให้เล็กลงเหลือเพียงเซลล์เดียว Google Pixel 4 คุณต้องตั้งค่าminResizeWidthไม่เกิน 56dp เพื่อตรวจสอบว่าค่าสำหรับแอตทริบิวต์ minResizeWidth เล็กลง 57dp เนื่องจากเซลล์กว้างอย่างน้อย 57dp ในแนวตั้ง ในทำนองเดียวกัน หากคุณต้องการปรับขนาดความสูงของวิดเจ็ตได้ในเซลล์เดียว อุปกรณ์เดียวกัน คุณต้องตั้งค่า minResizeHeight ไม่เกิน 50dp เพื่อให้มั่นใจว่า ค่าสำหรับแอตทริบิวต์ minResizeHeight น้อยกว่า 51dp เนื่องจากเซลล์หนึ่งมีความสูงอย่างน้อย 51dp ในโหมดแนวนอน

วิดเจ็ตแต่ละรายการสามารถปรับขนาดได้ภายในช่วงขนาดระหว่าง minResizeWidth/minResizeHeight และ maxResizeWidth/maxResizeHeight ซึ่งหมายความว่าต้องมีการปรับให้เข้ากับช่วงขนาดต่างๆ

เช่น หากต้องการกำหนดขนาดเริ่มต้นของวิดเจ็ตบนตำแหน่งโฆษณา ให้ทำดังนี้ ให้กำหนดแอตทริบิวต์ต่อไปนี้

<appwidget-provider
    android:targetCellWidth="3"
    android:targetCellHeight="2"
    android:minWidth="180dp"
    android:minHeight="110dp">
</appwidget-provider>

หมายความว่าขนาดเริ่มต้นของวิดเจ็ตคือ 3x2 เซลล์ ตามที่ระบุโดย แอตทริบิวต์ targetCellWidth และ targetCellHeight หรือ 180×110dp ตามขนาด ระบุโดย minWidth และ minHeight สำหรับอุปกรณ์ที่ใช้ Android 11 หรือต่ำกว่า ในกรณีหลัง ขนาดในเซลล์สามารถ แตกต่างกันไปตามอุปกรณ์

นอกจากนี้ หากต้องการกำหนดช่วงขนาดที่สนับสนุนของวิดเจ็ต คุณสามารถตั้งค่ารายการต่อไปนี้ ดังนี้

<appwidget-provider
    android:minResizeWidth="180dp"
    android:minResizeHeight="110dp"
    android:maxResizeWidth="530dp"
    android:maxResizeHeight="450dp">
</appwidget-provider>

ตามที่ระบุโดยแอตทริบิวต์ก่อนหน้า ความกว้างของวิดเจ็ตคือ ปรับขนาดได้ตั้งแต่ 180dp ถึง 530dp และความสูงสามารถปรับได้ตั้งแต่ 110dp ถึง 450dp จากนั้นวิดเจ็ตจะปรับขนาดได้ตั้งแต่ 3x2 ถึง 5x2 เซลล์ตราบเท่าที่เป็นไปตามเงื่อนไขต่อไปนี้ ที่มีอยู่:

Kotlin

val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small)
val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium)
val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large)

val viewMapping: Map<SizeF, RemoteViews> = mapOf(
        SizeF(180f, 110f) to smallView,
        SizeF(270f, 110f) to mediumView,
        SizeF(270f, 280f) to largeView
)

appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))

Java

RemoteViews smallView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small);
RemoteViews mediumView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium);
RemoteViews largeView = 
    new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large);

Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>();
viewMapping.put(new SizeF(180f, 110f), smallView);
viewMapping.put(new SizeF(270f, 110f), mediumView);
viewMapping.put(new SizeF(270f, 280f), largeView);
RemoteViews remoteViews = new RemoteViews(viewMapping);

appWidgetManager.updateAppWidget(id, remoteViews);

สมมติว่าวิดเจ็ตใช้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์ตามที่กำหนดไว้ใน ข้อมูลโค้ด ซึ่งหมายความว่าเลย์เอาต์ที่ระบุเป็น ใช้ R.layout.widget_weather_forecast_small ตั้งแต่ 180 dp (minResizeWidth) x 110dp (minResizeHeight) ถึง 269x279dp (จุดตัดถัดไปคือ 1) ในทำนองเดียวกัน R.layout.widget_weather_forecast_medium มีค่าตั้งแต่ 270x110dp ถึง 270x279dp และ R.layout.widget_weather_forecast_large ใช้ตั้งแต่ 270x280dp ถึง 530 dp (maxResizeWidth) x 450 dp (maxResizeHeight)

เมื่อผู้ใช้ปรับขนาดวิดเจ็ต รูปลักษณ์ของวิดเจ็ตจะเปลี่ยนไปเพื่อปรับให้เข้ากับแต่ละขนาด ดังที่ปรากฏในตัวอย่างต่อไปนี้

วันที่ ตัวอย่างวิดเจ็ตสภาพอากาศในขนาดตารางกริด 3x2 ที่เล็กที่สุด UI แสดง
            ชื่อสถานที่ (โตเกียว) อุณหภูมิ (14°) และสัญลักษณ์ที่ระบุ
            สภาพอากาศมีเมฆบางส่วน
รูปที่ 2 3x2 R.layout.widget_weather_forecast_small

วันที่ ตัวอย่างวิดเจ็ตสภาพอากาศใน &quot;ปานกลาง&quot; ขนาด 4x2 ขนาด การปรับขนาดวิดเจ็ต
            ด้วยวิธีนี้ วิดเจ็ตจะสร้างขึ้นบน UI ทั้งหมดจากขนาดวิดเจ็ตก่อนหน้า
            และเพิ่มป้ายกำกับ &quot;มีเมฆเป็นส่วนใหญ่&quot; และการคาดการณ์อุณหภูมิตั้งแต่
            16:00 น. - 19:00 น.
รูปที่ 3 4x2 R.layout.widget_weather_forecast_medium

วันที่ ตัวอย่างวิดเจ็ตสภาพอากาศใน &quot;ปานกลาง&quot; ขนาด 5x2 ขนาด การปรับขนาดวิดเจ็ต
            วิธีนี้จะทำให้ดู UI เหมือนกับขนาดก่อนหน้านี้ ยกเว้นว่า
            ยืดออกหนึ่งเซลล์เพื่อกินพื้นที่ในแนวนอนมากขึ้น
รูปที่ 4 5x2 R.layout.widget_weather_forecast_medium

วันที่ ตัวอย่างวิดเจ็ตสภาพอากาศใน &quot;ใหญ่&quot; ขนาด 5x3 ขนาด การปรับขนาดวิดเจ็ต
            วิธีนี้จะสร้างบน UI ทั้งหมดจากขนาดวิดเจ็ตก่อนหน้านี้
            และเพิ่มมุมมองภายในวิดเจ็ตที่มีพยากรณ์อากาศ
            ในวันอังคารและวันพุธ สัญลักษณ์แสดงสภาพอากาศที่มีแดดจัดหรือฝนตก
            และอุณหภูมิสูงสุดและต่ำสุดของแต่ละวัน
รูปที่ 5 5x3 R.layout.widget_weather_forecast_large

วันที่ ตัวอย่างวิดเจ็ตสภาพอากาศใน &quot;ใหญ่&quot; ขนาด 5x4 ขนาด การปรับขนาดวิดเจ็ต
            วิธีนี้จะสร้างบน UI ทั้งหมดจากขนาดวิดเจ็ตก่อนหน้านี้
            และเพิ่มวันพฤหัสบดีและวันศุกร์ (และสัญลักษณ์ที่สอดคล้องกัน)
            ระบุประเภทของสภาพอากาศ รวมทั้งอุณหภูมิสูงสุดและต่ำสุด
            สำหรับ 1 วัน)
รูปที่ 6 5x4 R.layout.widget_weather_forecast_large