UI ของ Android สร้างขึ้นจาก Views และในแอปพลิเคชันทั่วไปมักจะมีหลายตัว ในการทราบว่าผู้ใช้กำลังมอง View ใดอยู่ คุณต้องติดตั้ง Visibility Listeners
อ่านต่อไปนี้เพื่อค้นพบตัวเลือกต่างๆ ในการระบุสถานะการมองเห็นของ View
วิธีทำให้ View มองเห็นได้
เพื่อให้ Listener ทำงาน เราต้องตรวจสอบก่อนว่า View อยู่ในลำดับชั้นของ Layout แล้ว มี 2 วิธี:
- View ของคุณเป็นส่วนหนึ่งของ Layout ที่กำหนดในไฟล์ XML อยู่แล้ว
- คุณสร้าง View แบบไดนามิก และต้องเพิ่มเข้าไปโดยใช้เมธอด
addView
public void addView(View child, ViewGroup.LayoutParams params)
สถานะการมองเห็นของ View เป็นชนิด Integer และมี 3 ตัวเลือก:
- VISIBLE (0) - View มองเห็นได้โดยผู้ใช้
- INVISIBLE (4) - View ไม่มองเห็น แต่ยังคง佔พื้นที่ใน Layout
- GONE (8) - View ไม่มองเห็นและไม่佔พื้นที่ใน Layout
เมื่ออยู่ในลำดับชั้น Layout แล้ว มีตัวเลือก Native หลายตัวช่วยรู้ว่าเมื่อไหร่ Visibility ของ View เปลี่ยนแปลง
onVisibilityChanged
protected void onVisibilityChanged(View changedView, int visibility)
เมธอดนี้ถูกเรียกเมื่อ Visibility ของ View หรือของ Ancestor ของ View เปลี่ยนแปลง สถานะ Visibility จะอยู่ในพารามิเตอร์ visibility
onWindowVisibilityChanged
protected void onWindowVisibilityChanged(int visibility)
เมธอดนี้ถูกเรียกเมื่อ Window ที่บรรจุ View ของเราเปลี่ยนแปลง Visibility ไม่รับประกันว่า Window ที่ View อยู่มองเห็นได้จริง เนื่องจากอาจถูกบังโดย Window อื่น
Visibility Listeners ในการทำงานจริง
ลองสร้างโปรเจกต์ง่ายๆ เพื่อดู Listener ทั้งสองในการทำงาน เราจะมี LinearLayout พร้อม TextView และ Button การคลิก Button จะเพิ่ม Custom View เข้า Layout
Custom View ของเรา:
package com.tomerpacific.viewvisibility;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import static android.view.Gravity.CENTER;
public class MyCustomView extends LinearLayout {
private final String TAG = MyCustomView.class.getSimpleName();
public MyCustomView(Context context) {
super(context);
this.setBackgroundColor(Color.GREEN);
this.setGravity(CENTER);
TextView myTextView = new TextView(context);
myTextView.setText("My Custom View");
addView(myTextView);
}
@Override
public void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
Log.d(TAG, "View " + changedView + " changed visibility to " + visibility);
}
@Override
public void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
Log.d(TAG, "Window visibility changed to " + visibility);
}
}
โค้ดใน MainActivity:
package com.tomerpacific.viewvisibility;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private Button addCustomViewBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addCustomViewBtn = (Button) findViewById(R.id.addCustomViewBtn);
addCustomViewBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.mainLayout);
MyCustomView myCustomView = new MyCustomView(getApplicationContext());
myCustomView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
mainLayout.addView(myCustomView);
}
});
}
}
เมื่อรันแอปและกดปุ่ม จะได้ผลลัพธ์ดังนี้:
ดาวน์โหลดโปรเจกต์ตัวอย่างได้ ที่นี่
ViewTreeObserver
เป็น Object Native ที่มี Listener หลากหลายแจ้งเตือนการเปลี่ยนแปลง Visibility ของ View Tree ตัวสำคัญที่ควรสังเกต:
- OnGlobalLayoutListener
- OnWindowAttachListener
- OnWindowFocusChangeListener
วิธีแนบ ViewTreeObserver:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver viewTreeObserver = linearLayout.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// TODO Add Logic
}
});
บรรทัด linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this) ทำให้ Listener ถูกเรียกเพียงครั้งเดียว หากต้องการฟังต่อเนื่อง ให้ลบบรรทัดนี้ออก
หากมีคำถามหรือข้อเสนอแนะ สามารถแจ้งได้เลยครับ