ไม่ได้เขียนขึ้นเองครับ ใครอยากอ่านรายละเอียดเต็มๆตามไปอ่านลิงค์ ^ ได้เลยครับ
สรุป วิธีนี้ก็คือต้องการสร้างเป็น Custom View ตัวใหม่ขึ้นมา
โดยมี View อยู่ข้างในหลายๆตัว เพื่อให้ควบคุมสั่งงานจาก Custom View ตัวเดียวไปเลย
แทนที่จะไปนั่งควบคุม View แต่ละตัวให้โค้ดมันวุ่นวาย
Example : InfoCardView
widget_info_card.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff7200"
android:padding="16dp"
android:textColor="#ffffff"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:padding="16dp"
android:textColor="#333333"
android:textSize="16sp" />
</LinearLayout>
สร้าง Custom View สำหรับ InfoCardView
แนะนำว่าให้สืบทอดคลาสจาก FrameLayout
เพราะว่าการสร้าง Custom View ด้วยวิธีนี้คือการสร้าง Layout XML ที่ต้องการ
แล้วเอามาแปะใน Custom View ดังนั้น FrameLayout จึงเหมาะสมที่สุด
InfoCardView.kt
class InfoCardView : FrameLayout, View.OnClickListener {
var tvTitle : TextView? = null
var tvContent : TextView? = null
private var infoClickListener: InfoClickListener? = null
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
setup()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
setup()
}
private fun setup() {
inflate(context, R.layout.widget_info_card, this)
bindView()
setupView()
}
private fun bindView() {
tvTitle = findViewById(R.id.tv_title)
tvContent = findViewById(R.id.tv_content)
}
private fun setupView() {
tvTitle?.setOnClickListener(this)
tvContent?.setOnClickListener(this)
}
// สร้างฟังก์ชั่นไว้รอใช้งานใน MainActivity.kt
fun setTitle(title: String) {
tvTitle?.text = title
}
fun setContent(content: String) {
tvContent?.text = content
}
fun setInfoClickListener(listener: InfoClickListener) {
this.infoClickListener = listener
}
// ดักการคลิกของผู้ใช้ใน layout file : widget_info_card.xml
override fun onClick(view: View) {
if (view === tvTitle) {
onTitleClick()
} else if (view === tvContent) {
onContentClick()
}
}
// สร้าง Listener Onclick ให้ View
private fun onTitleClick() {
if (infoClickListener != null) {
infoClickListener!!.onTitleClick()
}
}
private fun onContentClick() {
if (infoClickListener != null) {
infoClickListener!!.onContentClick()
}
}
// สร้าง interface ไว้ใช้งานใน MainActivity.kt interface InfoClickListener {
fun onTitleClick()
fun onContentClick()
}
}
MainActivity.kt
class MainActivity : AppCompatActivity(), InfoCardView.InfoClickListener { // Implement InfoClickListener interface
private var icvAndroidVersion : InfoCardView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bindView()
setupView()
}
private fun bindView() {
icvAndroidVersion = findViewById<InfoCardView>(R.id.icv_android_version)
}
// เรียกใช้งาน ฟังก์ชั่นใน InfoCardView.kt
private fun setupView() {
icvAndroidVersion?.setTitle(getString(R.string.nougat_title))
icvAndroidVersion?.setContent(getString(R.string.nougat_content))
icvAndroidVersion?.setInfoClickListener(this)
}
// แสดง Pop up เมื่อคลิกที่ View : Title
override fun onTitleClick() {
Toast.makeText(this, "onTitleClick", Toast.LENGTH_LONG).show()
}
// แสดง Pop up เมื่อคลิกที่ View : Content
override fun onContentClick() {
Toast.makeText(this, "onContentClick", Toast.LENGTH_LONG).show()
}
}
ลองเรียกใช้งานเพื่อดูผลลัพธ์การทำงาน
<com.example.trymycustomview.InfoCardView
android:id="@+id/icv_android_version"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
อ่านต้นฉบับ + รายละเอียดแบบเต็มๆ
http://www.akexorcist.com/2016/12/introduction-to-custom-view-part-2.html