ปรับเกม Android ให้เหมาะกับขนาดหน้าจอที่แตกต่างกัน


11

ฉันกำลังสร้างเกม Android ที่อยู่ในแนวหน้าจอแนวตั้งเท่านั้น มันใช้งานได้ดีเมื่อฉันเรียกใช้บนโทรศัพท์ แต่เมื่อฉันเรียกใช้บนแท็บเล็ตแม้ว่าขนาดหน้าจอจะใหญ่กว่าบิตแมปทั้งหมดจะมีขนาดเท่ากัน มีวิธีใดที่จะทำให้บิตแมปอยู่ในสัดส่วนเดียวกันแม้บนหน้าจอขนาดต่างกันหรือไม่?

คำตอบ:


11

เว้นแต่ว่าคุณกำลังใช้AbsoluteLayout (โดยปกติแล้วเป็นความคิดที่แย่มากเมื่อคุณออกแบบเลย์เอาต์โดยใช้พิกัด x / y ซึ่งจะเหมาะกับอุปกรณ์ที่ได้รับการออกแบบมาเท่านั้น) สิ่งนี้ไม่ควรเกิดขึ้น - แอปพลิเคชัน Android จะปรับขนาดหน้าจอของอุปกรณ์โดยอัตโนมัติ . อย่างไรก็ตามจากสิ่งที่คุณอธิบาย (เค้าโครงไม่ปรับเป็นหน้าจอตาราง) ดูเหมือนว่า AbsoluteLayout อาจเป็นปัญหาที่นี่

ตรวจสอบให้แน่ใจว่าในไฟล์ XML เลย์เอาต์ของคุณคุณไม่ได้ใช้เลย์เอาต์แบบสัมบูรณ์ (ซึ่งรวมถึงการตั้งค่าพิกัด / ความกว้าง / ความสูงอย่างชัดเจนในมุมมองทุกประเภท) พิจารณาใช้แทน:

  • LinearLayout - วางซ้อนมุมมองหลาย ๆ แนวนอนหรือแนวตั้ง
  • FrameLayout - โดยปกติจะมีหนึ่งลูก
  • RelativeLayout - จัดตำแหน่งเด็กที่สัมพันธ์กัน
  • TableLayout - เค้าโครงตารางตาม
  • ScrollView - อาจมีรายการย่อยหนึ่งรายการ (เช่น LinearLayout) และให้คุณเลื่อนเนื้อหาได้

... สิ่งที่เหมาะสมที่สุดกับจุดประสงค์ของคุณ

หากคุณยังใหม่กับ Android Google มีการสอนที่ดีซึ่งแนะนำเกี่ยวกับประเภทการจัดหน้าต่าง ๆ ที่กล่าวถึงข้างต้น บทเรียนเพิ่มเติมสามารถพบได้ที่นี่

นอกจากนี้ระดับ API ของคุณก็มีความเกี่ยวข้องด้วย (เพื่อทราบว่าคุณใช้ Android 2.x หรือ 4.x - ฉันไม่คิดว่า 3.x เนื่องจากสมาร์ทโฟนใช้ไม่ได้) เพื่อหาสาเหตุของปัญหาของคุณ

คุณบังคับให้แอปพลิเคชันของคุณเข้าสู่โหมดแนวตั้งโดยการตั้งค่า:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set screen orientation for this dialog to portrait
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

... ในกิจกรรมของคุณที่แสดงมุมมองของเกม?

โปรดให้ข้อมูลเพิ่มเติมเกี่ยวกับวิธีการจัดวางมุมมองของคุณ (คุณใช้ XML สำหรับเค้าโครงที่คุณขยายในกิจกรรมของคุณหรือคุณใช้การจัดวางโค้ดในกิจกรรมของคุณเป็นต้น) นอกจากนี้: คุณลองใช้แอพของคุณในสมาร์ทโฟน - และเครื่องจำลองขนาดแท็บเล็ตหรือไม่? ถ้าใช่ปัญหายังคงอยู่หรือไม่?


อัปเดต: วิธีปรับขนาด BITMAPS

OP ถามว่าเขาสามารถปรับขนาดบิตแมปที่ใช้ในเกมได้อย่างไร ตัวเลือกหนึ่ง (จากทั้งหมดที่ฉันรู้เกี่ยวกับการตั้งค่าของ OP): SurfaceHolder.Callback ที่คุณกำลังเอาชนะเพื่อแสดงเกมของคุณและที่คุณแสดงบิตแมปทั้งหมด ฯลฯ ... มีวิธีการที่เรียกว่า:

surfaceChanged(SurfaceHolder holder, int format, int width, int height)

วิธีการนั้นให้ความกว้าง / ความสูงของพื้นผิวของคุณดังนั้นตอนนี้คุณสามารถใช้:

Bitmap.createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)

จากระดับ Bitmap เพื่อปรับขนาดภาพตามสัดส่วนของพื้นผิวที่คุณวาดลงไป

สิ่งที่คุณต้องทำคือ: ถ้าคุณรู้ขนาดของบิตแมปที่เกี่ยวข้องกับหน้าจอที่กำหนดตัวอย่างเช่นขนาดหน้าจอของสมาร์ทโฟนของคุณ จากนั้นคุณสามารถคำนวณขนาดเป้าหมายของบิตแมปที่ปรับขนาดได้ นี่คือคณิตศาสตร์ (ห่อในตัวอย่าง):

สมมติว่าคุณมีBitmap A ที่มีขนาด25x50 (ความกว้าง x ความสูง)ซึ่งแสดงบนหน้าจอที่มีขนาด 100x200 (ความกว้าง x ความสูง) สำหรับขนาดหน้าจอนั้น (100x200) บิตแมปมีขนาดที่ถูกต้อง - ตอนนี้ถ้าคุณต้องการแสดงบิตแมปบนหน้าจอที่ใหญ่ขึ้นคุณต้อง:

  • คำนวณตัวคูณสเกลสำหรับขนาดบิตแมป
  • รักษาอัตราส่วนภาพของบิตแมป (ดังนั้นจึงไม่ผิดเพี้ยน)

สมมติว่าหน้าจอที่ใหญ่ขึ้นคือ 200x300 (กว้าง x สูง) จากนั้นสเกลแฟคเตอร์สำหรับความกว้างคือ:

200(target screen width)/100(default screen width) = 2

ดังนั้น2คือสเกลแฟคเตอร์ของเราสำหรับความกว้างและความสูงของบิตแมปเนื่องจากเราต้องรักษาอัตราส่วนของบิตแมปเราสามารถคูณตัวคูณสเกลด้วยความกว้างและความสูงของบิตแมปได้:

bitmapWidth * 2 = scaledBitmapWidth
bitmapHeight * 2 = scaledBitmapHeight

ดังนั้นเมื่อใช้บิตแมปตัวอย่าง A จากด้านบนและสูตรที่กล่าวถึงมิติใหม่ของบิตแมปจะเป็น: 50x100 (widthxheight) เพราะ:

 2*25(width) = 50 height
 2*50(height) = 100 height

Soo ตอนนี้ที่เรารู้ขนาดใหม่ของบิตแมปของเราเราเพียงแค่ใช้การโทร API ที่ฉันกล่าวถึงข้างต้นและเติมในช่องว่าง:

   Bitmap.createScaledBitmap (myBitmap, 50, 100, false)

myBitmap ในตัวอย่างข้างต้นเป็นบิตแมปดั้งเดิม A ซึ่งมีขนาด 25x50 และถูกปรับสัดส่วนเป็น 50x100 โดยใช้โค้ดโค้ดด้านบน


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

  • คุณใช้โปรแกรมเกมเช่นAndEngineหรือUnityหรือไม่?
  • คุณเขียนเลย์เอาต์ของคุณเป็น xml หรือไม่? ถ้าใช่รูปแบบรูทของคุณสำหรับแสดงเนื้อหาเกมของคุณคืออะไร
  • คุณพูดถึงว่าคุณกำลังใช้ SurfaceHolder.Callback ความกว้าง / ความสูงที่ให้ไว้ในการเรียกใช้วิธีการของ surfaceChanged ให้ขนาดของพื้นผิว - มันมีขนาดเท่ากันเมื่อแอพของคุณทำงานบนสมาร์ทโฟนหรือแท็บเล็ตหรือไม่?
  • คุณมีการเข้าถึง SurfaceView (หรืออะไรก็ตามที่เชื่อมโยงกับ SurfaceHolder นั้นการโทรกลับที่คุณกำลังนำไปใช้) ดังนั้นเราสามารถตรวจสอบได้ว่าเป็นแอปหนึ่งที่ตั้งค่าขนาดแอพเป็นขนาดสมาร์ทโฟนอย่างแน่นหนา
  • ปัญหาการปรับขนาดเดียวกันนี้เกิดขึ้นในเครื่องจำลองที่มีความละเอียดหน้าจอแตกต่างกันหรือไม่?

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


ปรับปรุง: การปรับพิกัด x / y

ในการปรับตำแหน่งบิตแมปของคุณให้มีขนาดหน้าจอสิ่งต่อไปนี้ควรทำงาน:

  • ขนาดหน้าจอ: 100/200 (กว้าง / สูง)
  • ตำแหน่งบิตแมป: x = 50 / y = 100

ตอนนี้ถ้าคุณเพิ่มขนาดหน้าจอคุณจะต้องปรับขนาดค่า x / y ตาม:

  • ขนาดหน้าจอ: 200/400 (กว้าง / สูง)

สเกลแฟกเตอร์จะเท่ากับ 2 เนื่องจากความกว้างและความสูงเพิ่มขึ้นสองเท่า ๆ กัน ดังนั้นขนาดจะเป็น ...

  • ตำแหน่งบิตแมป: x = 100 / y = 200

ลองอีกครั้ง - คราวนี้มีปัจจัยขนาดแตกต่างกันสำหรับความกว้าง / ความสูง

  • ขนาดหน้าจอ: 100/150 (กว้าง / สูง)
  • ตำแหน่งบิตแมป: x = 50 / y = 50

หากหน้าจอเป้าหมายใหม่คือ 150/250 การคำนวณคือ:

  • ตัวประกอบสเกลสำหรับความกว้าง = targetWidth / originalWidth = 1.5
  • ตัวประกอบสเกลสำหรับส่วนสูง = targetHeight / originalHeight = 1.666 ... (จุด)

ตอนนี้เราจำเป็นต้องปรับขนาดพิกัด x / y, x ถูกปรับขนาดโดยใช้ความกว้างและความสูงถูกปรับขนาดโดยใช้ระดับความสูงนี่คือผลลัพธ์:

  • x = originalX * 1.5 = 75
  • y = originalY * 1.666 .. (รอบระยะเวลา) = 83.333 ... (ระยะเวลา)

ดังนั้นขนาดหน้าจอใหม่และพิกัด x / y ที่ปรับสเกลคือ:

  • width = 150
  • height = 250
  • x = 75
  • y = 83,333 ... (ระยะเวลา)

เพื่อทำให้เนื้อเรื่องสั้นสั้นอัลกอริทึมสำหรับการปรับบิตแมปคือ:

X = (targetScreenWidth / defaultScreenWidth) * defaultXCoordinate
Y = (targetScreenHeight / defaultScreenHeight) * defaultYCoordinate

เกมของฉันใช้แผงเกมที่ขยาย SurfaceHolder กลับมา (อยู่ในไฟล์ XML ที่ถูกเรียกโดยกิจกรรม) นี่อาจเป็นส่วนหนึ่งของปัญหาหรือไม่
user1404512

@ user1404512 SurfaceHolder.Callback มักจะเชื่อมโยงกับ SurfaceView - และยังขึ้นอยู่กับว่า SurfaceView ได้รับการกำหนดค่าอย่างไร (กว้าง / สูง) ถ้ามันถูกฝังในเลย์เอาต์อื่น (เช่น FrameLayout ฯลฯ ) ... ใน A SurfaceHolder ควรเป็นวิธีการ: พื้นผิวโมฆะสาธารณะเปลี่ยน (ผู้ถือ SurfaceHolder, รูปแบบ int, ความกว้าง int, ความสูง int) ความกว้างและความสูงควรเป็นขนาดของสิ่งที่ถูกวาดบนหน้าจอ - ซึ่งในกรณีของคุณจะเหมือนกันบนแท็บเล็ตและสมาร์ทโฟน คุณยืนยันหรือไม่
AgentKnopf

ใช่ฉันคิดว่าฉันควรพูดแบบนี้: เมื่อฉันเรียกใช้บนแท็บเล็ตแม้ว่าขนาดหน้าจอใหญ่กว่าบิตแมปทั้งหมดจะมีขนาดเท่ากัน มีวิธีใดที่จะทำให้บิตแมปอยู่ในสัดส่วนเดียวกันแม้บนหน้าจอขนาดต่างกันหรือไม่?
user1404512

@ user1404512 มันสำคัญมากที่คุณตอบคำถามเหล่านั้นทั้งหมดที่เราถามคุณเพราะเรายังอยู่ในความมืดเกี่ยวกับการออกแบบเลย์เอาต์ของคุณซึ่งทำให้ยากต่อการตอบคำถามเฉพาะ สำหรับบิตแมปของคุณ: ฉันได้อัปเดตคำตอบเพื่อตอบคำถามบิตแมป - มาตราส่วนที่ดีที่สุดเท่าที่จะทำได้
AgentKnopf

ไม่ฉันไม่ได้ใช้โปรแกรมเกม ฉันมีเลย์เอาต์ของฉันใน xml และในไฟล์ xml ของฉันฉันมี SurfaceHolder.Callback นั่นคือทั้งหน้าจอ ความกว้างและความสูงของตัวยึดเปลี่ยนจากหน้าจอเป็นหน้าจอ ฉันคิดว่าปัญหาของฉันคือฉันกำลังวาดบิตแมปที่มีพิกัด X และ Y แต่ขนาดของบิตแมปยังคงเท่าเดิมจากหน้าจอสู่หน้าจอ มีวิธีแก้ไขปัญหานี้หรือไม่? ขอบคุณมากในล่วงหน้า!
user1404512

3

มีบทความที่ดีและเกี่ยวข้องใน Android.com: http://developer.android.com/guide/practices/screens_support.html

ข้อมูลอ้างอิงนี้ช่วยคุณเรียงลำดับขนาดหน้าจอความหนาแน่นของหน้าจอและความละเอียด เป้าหมายคือการใช้ Android API เพื่อให้ได้ "ความหนาแน่นอิสระ" เพื่อให้ส่วนประกอบและกราฟิกส่วนติดต่อผู้ใช้ของคุณสามารถดูดีบนอุปกรณ์ต่าง ๆ

จำไว้ว่าคุณยังสามารถสร้างการกำหนดค่าที่แตกต่างกันของอุปกรณ์เสมือน Android สำหรับตัวจำลองในขณะที่คุณกำลังทดสอบรูปแบบและลักษณะที่ปรากฏ: http://developer.android.com/guide/developing/devices/emulator.html


0

แค่ถ่ายภาพในที่มืดที่นี่ คุณได้ตั้งค่าสิ่งที่รูปแบบหลักเพื่อเติมเต็มผู้ปกครองทั้งแนวตั้งและแนวนอนหรือไม่?

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.