หน้านี้อธิบายการปรับแต่งเพื่อปรับขนาดวิดเจ็ตและความยืดหยุ่นที่มากขึ้น เปิดตัวใน Android 12 (API ระดับ 31) และยังบอกรายละเอียดวิธีการ ระบุขนาดของวิดเจ็ต
ใช้ API ที่ปรับปรุงแล้วสำหรับขนาดและเลย์เอาต์วิดเจ็ต
ตั้งแต่ Android 12 (API ระดับ 31) เป็นต้นไป คุณจะระบุขนาดที่ละเอียดยิ่งขึ้นได้ และเลย์เอาต์ที่ยืดหยุ่นได้โดยทำดังนี้ ดังที่อธิบายไว้ใน ส่วนต่างๆ ที่ตามมา:
ใน 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
: กำหนดขนาดสูงสุดที่ Launcher อนุญาตให้ผู้ใช้ปรับขนาดวิดเจ็ต
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) × 200dpwideView
รองรับขนาดตั้งแต่ 215dp × 110dp (minResizeHeight
) ถึง 250dp (maxResizeWidth
) × 200dp (maxResizeHeight
)
วิดเจ็ตต้องรองรับขนาดตั้งแต่ minResizeWidth
×
minResizeHeight
ถึง maxResizeWidth
× maxResizeHeight
ภายในช่วงดังกล่าว
คุณจะเลือกจุดตัดเพื่อเปลี่ยนเลย์เอาต์ได้
ระบุเลย์เอาต์ที่แน่นอน
หากไม่สามารถใช้เลย์เอาต์ที่ปรับเปลี่ยนตามอุปกรณ์ชุดเล็กๆ ให้คุณระบุ รูปแบบต่างๆ ที่ปรับแต่งให้เหมาะกับขนาดที่วิดเจ็ตแสดง ซึ่งโดยทั่วไปแล้วจะมี 2 ขนาดสําหรับโทรศัพท์ (โหมดแนวตั้งและแนวนอน) และ 4 ขนาดสําหรับโทรศัพท์แบบพับได้
ในการใช้โซลูชันนี้ แอปของคุณต้องทำตามขั้นตอนต่อไปนี้
โอเวอร์โหลด
AppWidgetProvider.onAppWidgetOptionsChanged()
ซึ่งจะถูกเรียกเมื่อชุดของขนาดมีการเปลี่ยนแปลงโทร
AppWidgetManager.getAppWidgetOptions()
ซึ่งแสดงผลBundle
ที่มีขนาดเข้าถึงคีย์
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 เซลล์ได้ ตราบใดที่มีคุณสมบัติตรงตามเงื่อนไขต่อไปนี้
- อุปกรณ์มีตารางกริดขนาด 5x4
- การจับคู่ระหว่างจำนวนเซลล์และขนาดที่ใช้ได้ในหน่วย dps เป็นไปตามตารางที่แสดงการประมาณค่าขั้นต่ำ มิติข้อมูลในหน้านี้
- วิดเจ็ตจะปรับขนาดให้เข้ากับช่วงขนาดนั้น
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
ตั้งแต่ 180dp (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
)
เมื่อผู้ใช้ปรับขนาดวิดเจ็ต ลักษณะที่ปรากฏของวิดเจ็ตจะเปลี่ยนไปเพื่อปรับให้เข้ากับขนาดแต่ละขนาดในเซลล์ ดังที่แสดงในตัวอย่างต่อไปนี้