หน้านี้จะอธิบายการปรับแต่งขนาดวิดเจ็ตและความยืดหยุ่นที่มากขึ้นซึ่งเปิดตัวใน 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
รองรับตั้งแต่ 160dp (minResizeWidth
) × 110dp (minResizeHeight
) ถึง 160dp × 199dp (จุดตัดถัดไป - 1dp)tallView
รองรับขนาดตั้งแต่ 160dp × 200dp ถึง 214dp (จุดตัดถัดไป - 1) × 200dpwideView
รองรับขนาดตั้งแต่ 215dp × 110dp (minResizeHeight
) ถึง 250dp (maxResizeWidth
) × 200dp (maxResizeHeight
)
วิดเจ็ตต้องรองรับขนาดตั้งแต่ minResizeWidth
×
minResizeHeight
ถึง maxResizeWidth
× maxResizeHeight
ภายในช่วงดังกล่าว คุณสามารถเลือกจุดตัดเพื่อเปลี่ยนเลย์เอาต์ได้
ระบุเลย์เอาต์ที่แน่นอน
หากเลย์เอาต์ที่ปรับเปลี่ยนตามพื้นที่โฆษณาชุดเล็กไม่เหมาะสําหรับการใช้งาน คุณระบุเลย์เอาต์อื่นที่ปรับให้เหมาะกับขนาดที่วิดเจ็ตแสดงแทนได้ ซึ่งโดยทั่วไปจะมี 2 ขนาดสําหรับโทรศัพท์ (โหมดแนวตั้งและแนวนอน) และ 4 ขนาดสําหรับโทรศัพท์แบบพับได้
ในการใช้โซลูชันนี้ แอปของคุณต้องทำตามขั้นตอนต่อไปนี้
Overload
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 |
... | ... | ... |
n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
ใช้ขนาดเซลล์ในโหมดแนวตั้งเพื่อแจ้งค่าที่คุณระบุสำหรับแอตทริบิวต์ minWidth
, minResizeWidth
และ maxResizeWidth
ในทำนองเดียวกัน ให้ใช้ขนาดเซลล์ในโหมดแนวนอนเพื่อระบุค่าที่คุณระบุสำหรับแอตทริบิวต์ minHeight
, minResizeHeight
และ maxResizeHeight
สาเหตุคือโดยทั่วไปแล้วความกว้างของเซลล์ในโหมดแนวตั้งจะแคบกว่าในโหมดแนวนอน และในทางกลับกัน ความสูงของเซลล์ในโหมดแนวนอนจะแคบกว่าในโหมดแนวตั้ง
เช่น หากต้องการให้ปรับขนาดความกว้างวิดเจ็ตได้จนถึง 1 เซลล์ใน 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 ถึง 530dp (maxResizeWidth
) x 450dp (maxResizeHeight
)
เมื่อผู้ใช้ปรับขนาดวิดเจ็ต รูปลักษณ์ของวิดเจ็ตจะเปลี่ยนไปเพื่อปรับให้เข้ากับแต่ละขนาดในเซลล์ ดังที่แสดงในตัวอย่างต่อไปนี้