measure()

คราวที่แล้วเขียนไปแค่สี่ขั้นตอน แต่ถ้าใครลองโหลดไฟล์ที่ @iporsut แนบมาใน comment คงเห็นรายละเอียดที่มากกว่านั้นเยอะแยะเลย แต่ผมก็ได้แค่อ่านผ่านๆ นะ ยังไม่ได้ดูละเอียดเท่าไหร่ แหะๆ แต่วันนี้จะมาเขียนถึงขั้นลึกลับอีกขั้นนึงนั่นคือ measure() เพราะต้องใช้มันเข้าพอดี -_-”
ปกติฟังก์ชั่นนี้จะไม่ค่อยต้องเขียนเองเท่าไหร่เพราะหน้าที่ของมันคือใช้บอกว่า component เรามีขนาดเท่าไหร่ แล้วให้ขั้นถัดไปคือ updateDisplayList เป็นคนวาด ซึ่งวิธีทำปกตินั้นก็ง่ายแสนง่ายคือเรียก component ลูกให้วัดค่าออกมาให้ แล้วก็จับมันบวกๆ ลบๆ กันแล้วส่งออกไป แต่มีปัญหากับผมอีกและ -_-” เพราะว่าถ้าหากเราตั้งขนาดของ component ลูกเป็น % แล้วหละก็มันก็มีบางอย่างที่คำนวนออกมาให้พลาดเหมือนกัน(จริงๆ ก็ไม่พลาดหรอกแต่ผลลัพธ์ที่ต้องการมันไม่ไช่อย่างนั้นหนะ) เช่น List ลองมาดูโจทย์ผมละกัน
โจทย์ก็แสนจะง่ายดาย มี List ย่อยๆ หลายๆ List ที่แต่ละ List มีข้อมูลไม่เท่ากัน โดยต้องเอา List เหล่านั้นมารวมกันให้เป็น List ใหญ่ๆ ก้อนนึง อ๊ะ เหมือนธรรมดา ยังไม่หมดๆ แต่ละ List มีสองแบบคือ List ที่เป็นแบบแถวเรียงลงมา กับ List ที่เป็นแบบกล่องไอคอน แบบที่เห็นใน Nautilus หรือ My computer นั่นแหละ ซับซ้อนดีมะ ซึ่งแต่ละ List ก็ต้องโชว์ขนาดทั้งหมดอีก เอาเป็นว่าคงไม่เห็นภาพกันแน่นอน ไปดูของจริงเลยดีกว่า

อ่ะคราวนี้จากด้านบนถ้าตั้ง List แต่ละอันว่าให้ขนาดเป็น 100% มันก็จะไม่สามารถรู้ได้อีกว่ามันควรจะให้ความสูงมันเป็นเท่าไหร่ ผลก็คือมันจะให้กล่องแต่ละกล่องมีขนาดเท่ากันหมด และย่อเหลือแสดงแค่สองแถวเท่านั้น (จริงๆ ข้อมูลด้านบนมันไม่ดีนะเนี๊ยะ ช่องบนกับช่องล่างข้อมูลมีขนาดเท่ากัน -_-”) วิธีแก้คือไป override measure() ซะโดยคำนวนขนาดของแต่ละแถวของ List ว่ามีความสูงเท่าไหร่ จับบวกลบคูณหารนิดหน่อยยัดใส่ตัวแปรชื่อ measuredHeight ก็เป็นอันจบ พอไปถึงขั้นถัดไปคือ updateDisplayList มันจะวาดกล่องต่างๆ ตามขนาดที่เรากำหนดใน measuredWidth กับ measuredHeight

protected override function measure():void {
  super.measure()

  if (stack.selectedChild == listCanvas) {
    measuredHeight = titleBar.measuredHeight + list.measureHeightOfItems(0, provider.length + 1)
  } else {
    if (providerLength != provider.length || tileRowCount < 0) {
      providerLength = provider.length
      tileRowCount = tile.rowCount + 1
    }

    measuredHeight = titleBar.measuredHeight + tileRowCount * tile.rowHeight
  }
}

จริงๆ มันเล่น measuredWidth ได้ด้วยแต่ว่าผมไม่ต้องใช้อ่ะ เพราะยังไงมันก็กว้าง 100% อยู่แล้ว เลยเล่นแต่ Height แต่ถ้า List มันกลายเป็นแนวนอนก็ไม่แน่ และก็โค้ด: complexlist
เพิ่มเติม: โค้ดบางส่วนผมก็หยิบยืมมาจากเพื่อนในส่วนที่ใช้จริงอยู่นะครับ (แต่เพื่อนไม่อยู่แล้วอ่ะ ~ ~") เช่นพวก ToggleLink, TriangleLink เพื่อนจะใช้ object graphics เป็นตัววาดไม่ได้ embed graphics เข้าไป ถ้าอยากถามรายละเอียด ก็รอผมแกะให้หมดก่อนละกันนะ(จริงๆ ก็อธิบายได้แหละว่าทำงานยังไง ไม่ยากหรอก)
ปอลอ. ถ้าตัวอย่างด้านบนแสดงผลเพี้ยนๆ ตอนเปลี่ยน View จาก List เป็น Tile บน Windows อันนั้นยังหาวิธีแก้ไม่ได้นะ แต่บน Linux มันแสดงผลถูกต้องอ่ะ - -" วัดแล้วขยับความสูงลดลงไป ไม่รู้ทำไมเหมือนกัน

About llun

Just a programmer

, ,

  • http://www.flexdev.info/forum iporsut

    ขอบคุณมากเลย
    กำลังอยากจะบอกให้ช่วยอธิบายเรื่องนี้อยู่พอดีเลย