วิธีสร้างตัวแบ่งแบบง่ายใน NavigationView ใหม่


154

Google เปิดตัวNavigationViewใน Design Support Library เวอร์ชัน 22.2.0 ซึ่งคุณสามารถสร้าง drawer ได้อย่างง่ายดายโดยใช้ทรัพยากรเมนู

ฉันจะสร้างเส้นแบ่งอย่างง่ายระหว่างสองรายการได้อย่างไร การจัดกลุ่มรายการไม่ทำงาน การสร้างส่วนรายการย่อยจะสร้างบรรทัดตัวแบ่ง แต่ต้องใช้ชื่อซึ่งฉันไม่ต้องการ

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชม


ดังที่ระบุไว้ในความคิดเห็นต่อปัญหาที่เกิดขึ้นกับคำตอบที่ยอมรับคือพฤติกรรมที่ตรวจสอบได้ไม่สามารถทำงานได้ในหลาย ๆ กลุ่ม (ขนาน) เพื่อหลีกเลี่ยงปัญหานี้อย่าสร้างกลุ่มคู่ขนาน แต่ใช้เมนูย่อยหรือกลุ่มย่อยเพื่อรับตัวแบ่งตามที่อธิบายไว้ในคำตอบของฉันที่นี่: stackoverflow.com/questions/30766919/…
จนถึง

คำตอบ:


319

สิ่งที่คุณต้องทำคือกำหนดgroupด้วยรหัสเฉพาะฉันได้ตรวจสอบการใช้งานหากกลุ่มมีรหัสที่แตกต่างกันมันจะสร้างตัวแบ่ง

เมนูตัวอย่างการสร้างตัวคั่น:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">

    <group android:id="@+id/grp1" android:checkableBehavior="single" >
        <item
            android:id="@+id/navigation_item_1"
            android:checked="true"
            android:icon="@drawable/ic_home"
            android:title="@string/navigation_item_1" />
    </group>

    <group android:id="@+id/grp2" android:checkableBehavior="single" >
        <item
            android:id="@+id/navigation_item_2"
            android:icon="@drawable/ic_home"
            android:title="@string/navigation_item_2" />
    </group>
</menu>

9
สงสัยว่าทำไมถึงเป็นแบบนี้ (เท่าที่ฉันรู้) ไม่ได้บันทึกไว้ ฉันคิดว่ามันจะถูกถามมาก ขอบคุณ!
เกียนแทน

16
ปัญหาอย่างหนึ่งของวิธีนี้คือsetCheckedดูเหมือนว่าจะทำงานในระดับกลุ่ม หากคุณเลือกรายการในกลุ่ม A จากนั้นเปิดลิ้นชักอีกครั้งและเลือกรายการในกลุ่ม B ทั้งสองรายการจะยังคงเน้นอยู่ บางที Google อาจแก้ไขพฤติกรรมนี้ในรุ่นถัดไป แต่ในตอนนี้ข้อเสียของการใช้หลายกลุ่มด้วย NavigationView
hungryghost

3
ยิ่งใหญ่ เกี่ยวกับการตรวจสอบสองครั้งลองandroid:checkableBehavior="none"สำหรับกลุ่มที่สองของคุณ (นั่นคือการกระทำไม่ใช่การนำทางฉันถือว่า)
espinchi

12
สิ่งที่ตลกถ้าคุณลบรหัสจากgroupมันจะรวบรวมและเรียกใช้ แต่ตัวแบ่งจะถูกซ่อนไว้
Vahid Amiri

5
สิ่งนี้ไม่ได้ผลสำหรับฉันเช่นกัน ฉันต้องการเส้นระหว่างกลุ่มเมนูไม่ใช่หลังจากแต่ละรายการ
Rich Morey

54

สร้าง drawable drawer_item_bg.xmlแบบนี้

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape android:shape="rectangle" >
            <solid android:color="#F4F4F4" />
        </shape>
    </item>

    <item android:top="-2dp" android:right="-2dp" android:left="-2dp">
        <shape>
            <solid android:color="@android:color/transparent" />
            <stroke
                android:width="1dp"
                android:color="#EAEAEA" />
        </shape>
        <!--
        android:dashGap="10px"
                android:dashWidth="10px"
                -->
    </item>

</layer-list>

และเพิ่มลงใน NavigationView เป็นแอพ: itemBackground = "@ drawable / drawer_item_bg"

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="#F4F4F4"
        android:layout_gravity="start"
        android:fitsSystemWindows="false"
        app:menu="@menu/activity_main_drawer"
        app:itemBackground="@drawable/drawer_item_bg"/>

และที่นี่เราไป ...ป้อนคำอธิบายรูปภาพที่นี่


1
ใช้งานได้ แต่จะลบไอคอนช่องด้านซ้ายออกด้วย อย่างน้อยในรหัสของฉันไม่ใช่ในภาพหน้าจอของคุณด้วยเหตุผลบางประการ
luky

@vbp ฉันต้องการเส้นขอบด้านบนสำหรับลูกคนแรกขอบด้านล่างสำหรับลูกคนอื่น ฉันจะประสบความสำเร็จได้อย่างไร มันเป็นสิ่งที่คล้ายกับเด็ก id.first ใน CSS
Prabs

@Prabs พิจารณาการใช้ชิ้นส่วน, recyclerview หรือที่กำหนดเองมุมมองแทน NavigationView สำหรับการปรับแต่งที่ดีกว่า
vbp

1
ฉันทำnavMenuView.addItemDecoration(new DividerItemDecoration(NavigationViewActivity.this, DividerItemDecoration.VERTICAL));เพื่อชายแดนรายการที่สมบูรณ์แบบ
Prabs

19

เพิ่ม DeviderItemDecoration ง่าย ๆ :

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
NavigationMenuView navMenuView = (NavigationMenuView) navigationView.getChildAt(0);
navMenuView.addItemDecoration(new DividerItemDecoration(MainActivity.this,DividerItemDecoration.VERTICAL));

ดูเหมือนว่านี้:

ป้อนคำอธิบายรูปภาพที่นี่


ฉันสามารถเปลี่ยนความสูงของaddItemDecorationบรรทัดเป็น 1px ได้หรือไม่
Prabs

ขอบคุณโซลูชันของคุณใช้งานได้สำหรับฉัน ข้าพเจ้าซาบซึ้ง. คำถามอีกข้อหนึ่งกับเรื่องนี้ เป็นไปได้ไหมที่จะลบเส้นขอบด้านบนของรายการแรกและตั้งค่าเส้นขอบเฉพาะที่ด้านล่างของรายการ
viper

@viper โปรดอ้างอิงสิ่งนี้: bignerdranch.com/blog/…
SANAT

1
ตัวคั่นชนิดนั้นสำหรับแต่ละรายการไม่เป็นไปตามหลักเกณฑ์วัสดุ
Boris Ruzanov

19

คุณสามารถเพิ่มตัวแบ่งได้อย่างง่ายดายโดยการตั้งค่าพื้นหลังรายการเมนูผ่าน XML โดยใช้ app:itemBackground

<android.support.design.widget.NavigationView
    android:id="@id/drawer_navigation_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/all_navigation_menu"
    app:itemIconTint="@color/colorPrimary"
    app:itemBackground="@drawable/bg_drawer_item"
    android:background="@color/default_background"/>

และใช้LayerDrawableเป็นพื้นหลัง มันรักษาการซ้อนทับระลอกการออกแบบวัสดุสำหรับการคลิก

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
        </shape>
    </item>
    <item android:left="@dimen/activity_horizontal_margin">
        <shape android:shape="rectangle">
            <solid android:color="@color/divider"/>
        </shape>
    </item>
    <item android:bottom="1dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/white"/>
        </shape>
    </item>
</layer-list>

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่


2
ดูเหมือนจะเป็นคำตอบที่ดีที่สุดและไม่มีกลุ่มที่เกี่ยวข้อง
Michał Ziobro

ถ้าคุณต้องการใช้สีพื้นหลังแบบกำหนดเองสำหรับรายการที่เลือก
ataravati

ฉันมีข้อผิดพลาดเกี่ยวกับ <shape>: องค์ประกอบไม่ได้รับอนุญาตที่นี่
Sébastien REMY

11

ฉันคิดว่าฉันมีทางออกที่ดียิ่งขึ้นสำหรับปัญหาของรายการตรวจสอบหลายรายการ ด้วยวิธีการของฉันคุณไม่ต้องกังวลกับการเปลี่ยนรหัสของคุณเมื่อเพิ่มส่วนใหม่ในเมนูของคุณ เมนูของฉันดูเหมือนกับโซลูชั่นที่เป็นที่ยอมรับซึ่งเขียนโดย Jared โดยมีความแตกต่างของการใช้ andoid: checkableBehavior = " all " ในกลุ่ม:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:id="@+id/first_section" android:checkableBehavior="all">
        <item
            android:id="@+id/frontpage"
            android:icon="@drawable/ic_action_home_24dp_light_blue"
            android:title="@string/drawer_frontpage" />
        <item
            android:id="@+id/search"
            android:icon="@drawable/ic_search"
            android:title="@string/drawer_search" />
    </group>
    <group android:id="@+id/second_section" android:checkableBehavior="all">
        <item
            android:id="@+id/events"
            android:icon="@drawable/ic_maps_local_movies_24dp_light_blue"
            android:title="@string/drawer_events" />
    </group>
</menu>

checkableBehavior ของ 'ทั้งหมด' ทำให้สามารถตรวจสอบ / ยกเลิกการเลือกรายการเดียวที่จะเป็นอิสระจากกลุ่มที่พวกเขาอยู่ คุณเพียงแค่ต้องเก็บ Menuitem ที่ตรวจสอบล่าสุด รหัส java มีลักษณะดังนี้:

private MenuItem activeMenuItem;

@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
    // Update selected/deselected MenuItems
    if (activeMenuItem != null)
        activeMenuItem.setChecked(false);
    activeMenuItem = menuItem;
    menuItem.setChecked(true);

    drawerLayout.closeDrawers();
    return true;
}

8

การสร้างกลุ่มที่แตกต่างกันเช่นคำตอบของ Nilesh ทำให้ตัวแบ่งในระหว่าง แต่สร้างปัญหาของสองรายการที่ตรวจสอบในลิ้นชัก nav

วิธีง่ายๆในการจัดการสิ่งนี้คือ:

    public boolean onNavigationItemSelected(final MenuItem menuItem) {

    //if an item from extras group is clicked,refresh NAV_ITEMS_MAIN to remove previously checked item
    if (menuItem.getGroupId() == NAV_ITEMS_EXTRA) {


        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, false, true);
        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, true, true);
       }else{

        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, true, true);
        navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, false, true);


    }
    //Update highlighted item in the navigation menu
    menuItem.setChecked(true);
}

ง่ายยิ่งขึ้น:android:checkableBehavior="none"
espinchi

2
@espinchi - จะไม่ทำงานหากกลุ่มอื่นมีรายการเมนูนำทาง วิธีนี้สามารถใช้งานได้กับการกระทำเท่านั้น การปฏิบัติ UX ไม่ดี
Mushtaq Jameel

ยอดเยี่ยม มันอาจจะชัดเจนขึ้นถ้าคุณเปลี่ยนค่าคงที่ที่ไม่ได้กำหนด NAV_ITEMS_MAIN และ NAV_ITEMS_EXTRA ด้วย R.id.nav_items_group_main หรือ R.id.nav_items_group_extra และเพิ่ม XML ที่จำเป็นสำหรับตัวอย่างของคุณ
ChrisPrime

IS onNavigationItemSelected (เมนูสุดท้าย ItemItem menu) {วิธีการเริ่มต้นหรือไม่ ฉันควรทำรหัสนี้ที่ไหน
จอห์น

NAV_ITEMS_MAIN คืออะไร
จอห์น

8

ฉันไม่แน่ใจว่าสิ่งนี้ได้รับการแก้ไขAPI 26 (Android 8)หรือไม่หรือเป็นไปได้ตลอดเวลา ฉันยังคงเป็น noob ในการเขียนโปรแกรม Android อย่างไรก็ตามฉันเพิ่มกลุ่มผู้ปกครองดังนี้ การทดสอบทางโทรศัพท์ Android 6

  1. ฉันมีตัวหาร
  2. เลือกรายการใดก็ได้จากnav_g1หรือnav_g2จะยกเลิกการเลือกรายการอื่น
  3. ไม่มีการเพิ่มส่วนเสริมพิเศษเนื่องจากกลุ่มที่ซ้อนกัน
  4. ฉันไม่ได้เพิ่มJavaรหัสใด ๆให้ผู้ฟัง

รหัสเมนู

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <group
            android:id="@+id/nav_g1"
            android:checkableBehavior="single">
            <item
                android:id="@+id/nav_1"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_1"/>
            <item
                android:id="@+id/nav_2"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_2"/>
        </group>
        <group
            android:id="@+id/nav_g2"
            android:checkableBehavior="single">
            <item
                android:id="@+id/nav_3"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_3"/>
            <item
                android:id="@+id/nav_4"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_4"/>
        </group>
    </group>
    <item android:title="Actions">
        <menu>
            <item
                android:id="@+id/nav_7"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_7"/>
            <item
                android:id="@+id/nav_8"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/nav_8"/>
        </menu>
    </item>
</menu>

หมายเหตุ

  1. ดังที่กล่าวไว้ในคำตอบนี้แต่ละกลุ่มจะต้องมีรหัสที่ไม่ซ้ำกันเพื่อแสดงตัวแบ่ง
  2. ตามนี้คำตอบช่องว่างจะตรงกับรายละเอียดการออกแบบวัสดุที่ Google
  3. จำเป็นต้องมีandroid:checkableBehavior="single"สำหรับผู้ปกครองกลุ่มดังนั้นปัญหาของรายการเมนูที่เลือกหลายรายการในคำตอบนี้ (กล่าวถึงในความคิดเห็นโดย hungryghost) จะไม่เกิดขึ้น

และนี่คือภาพหน้าจอ

สกรีนช็อตของหน้าจออุปกรณ์


5

ฉันต้องการวงเวียนด้านบนรายการแรกและหลังรายการสุดท้าย การใช้โซลูชัน @Nilesh ฉันต้องเพิ่มรายการเมนูจำลองและเปิดใช้งานการตั้งค่าเป็นเท็จซึ่งรู้สึกสกปรกจริงๆ นอกจากนี้หากฉันต้องการทำสิ่งดีๆอื่น ๆ ในเมนูของฉัน

ฉันสังเกตว่า NavigationView ขยาย FrameLayout เพื่อให้คุณสามารถใส่เนื้อหาของคุณเองลงไปในมันเหมือนที่คุณทำกับ FrameLayout ฉันตั้งค่าเมนูว่าง xml เพื่อให้มันแสดงเฉพาะเลย์เอาต์ที่กำหนดเองของฉัน ฉันเข้าใจว่าสิ่งนี้อาจขัดกับเส้นทางที่ Google ต้องการให้เราทำ แต่ถ้าคุณต้องการเมนูที่กำหนดเองอย่างแท้จริงนี่เป็นวิธีที่ง่ายในการทำ

<!--Note: NavigationView extends FrameLayout so we can put whatever we want in it.-->
<!--I don't set headerLayout since we can now put that in our custom content view-->
<android.support.design.widget.NavigationView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:menu="@menu/empty_menu">

    <!--CUSTOM CONTENT-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- CUSTOM HEADER -->
        <include
            android:id="@+id/vNavigationViewHeader"
            layout="@layout/navigation_view_header"/>

        <!--CUSTOM MENU-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_below="@+id/vNavigationViewHeader">

            <View style="@style/NavigationViewLineSeperator"/>

            <Button android:text="Option 1"/>

            <View style="@style/NavigationViewLineSeperator"/>

            <Button android:text="Option 2"/>

            <View style="@style/NavigationViewLineSeperator"/>

        </LinearLayout>
    </RelativeLayout>
</android.support.design.widget.NavigationView>

นี่คือสไตล์

<style name="NavigationViewLineSeperator">
        <item name="android:background">@drawable/line_seperator</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">1dp</item>
</style>

และ drawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@color/white"/>
    <size android:width="100sp"
          android:height="1sp" />
</shape>

และเมนู

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
</menu>

แก้ไข:

แทนที่จะใช้ปุ่มคุณสามารถใช้ TextView พร้อม drawable ซึ่งเลียนแบบรายการเมนูต้นฉบับที่มีลักษณะ:

 <TextView
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:text="@string/menu_support"
     android:drawableLeft="@drawable/menu_icon_support"
     style="@style/MainMenuText" />

// style.xml
<style name="MainMenuText">
    <item name="android:drawablePadding">12dp</item>
    <item name="android:padding">10dp</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:textColor">#fff</item>
</style>

1
ขอบคุณดูเหมือนจะเป็นวิธีที่สะดวกที่สุดในการมีมุมมองที่กำหนดเองเป็นรายการเมนู
Jan Rabe

ฉันใช้โซลูชันนี้ด้วยเพราะมันช่วยให้ฉันตั้งค่าแบบอักษรที่กำหนดเองของรายการได้ง่ายขึ้นและเปลี่ยนสีตัวแบ่ง
luky

1

เครดิตควรไปที่ Zorawar เพื่อการแก้ปัญหาขออภัยในการทำซ้ำคำตอบ แต่ไม่สามารถเพิ่มข้อความที่จัดรูปแบบมากในความคิดเห็น

โซลูชันของ Zorawar ใช้งานได้รหัสสามารถปรับปรุงได้เช่น:

public void onNavigationItemSelected(int groupId) {

    //if an item from extras group is clicked,refresh NAV_ITEMS_MAIN to remove previously checked item
    navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, (groupId == NAV_ITEMS_MAIN), true);
    navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, (groupId == NAV_ITEMS_EXTRA), true);


    //Update highlighted item in the navigation menu
    menuItem.setChecked(true);
}

NAV_ITEMS_MAIN และ NAV_ITEMS_EXTRA คืออะไรและ groupid ??
จอห์น

พวกเขาเป็นค่าคงที่สำหรับ group_id
Mushtaq Jameel

0

คำตอบของ Nileh นั้นถูกต้องเว้นแต่จะมีการตรวจสอบซ้ำสองครั้ง

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single" android:id="@+id/grp1">
        <item
            android:id="@+id/nav_register_customer"
            android:icon="@drawable/ic_menu_camera"
            android:checkableBehavior="none"
            android:title="Register Customer" />
    </group>
    <group  android:id="@+id/grp2"
        android:checkableBehavior="single"  >
        <item
            android:id="@+id/nav_slideshow"
            android:icon="@drawable/ic_menu_slideshow"
            android:checkableBehavior="none"
            android:title="Slideshow" />
    </group>
</menu>

ดังนั้นการใช้

หุ่นยนต์: checkableBehavior = "เดียว"

ด้วยรหัสเฉพาะจะต้องแก้ปัญหา


0

หากคุณต้องการเพิ่มตัวแบ่งแบบไดนามิกคุณสามารถเพิ่ม SubMenu ที่ว่างเปล่าเช่นนี้:

Menu menu = navigationView.getMenu();
menu.addSubMenu(" ").add(" ");

จะเป็นการเพิ่มตัวแบ่ง

เพียงให้แน่ใจว่าจะผ่านดัชนีที่ถูกต้องเมื่อใช้ menu.getItem(int index)


0

นอกเหนือจากคำตอบก่อนหน้าหากคุณต้องการตัวแยกการตกแต่ง แต่ไม่ต้องการสร้างหลายกลุ่มเนื่องจากปัญหา "พฤติกรรมที่ตรวจสอบได้" คุณสามารถกำหนดรหัสกลุ่มเดียวกันให้กับกลุ่มทั้งหมดของคุณ

ตัวอย่าง:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
    android:id="@+id/group_nav_common" <!-- New group id-->
    android:checkableBehavior="single">

    <item
        android:id="@+id/menu_item_nav_home"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/nav_menu_main" />
    <item
        android:id="@+id/menu_item_nav_articles"
        android:icon="@drawable/ic_art_track_black_24dp"
        android:title="@string/latest_news" />

    <item
        android:id="@+id/menu_item_nav_group_categories"
        android:title="@string/nav_menu_sections">
        <menu>
            <group
                android:id="@id/group_nav_common" <!-- Existing group id -->
                android:checkableBehavior="single">
                <!-- Programmatically populated section -->
            </group>
        </menu>
    </item>

    <item
        android:id="@+id/menu_item_nav_group_sites"
        android:title="@string/nav_menu_sites">
        <menu>
            <group
                android:id="@id/group_nav_common" <!-- Existing group id -->
                android:checkableBehavior="single">
                <item
                    android:id="@+id/menu_item_nav_select_site"
                    android:icon="@drawable/ic_account_balance_black_24dp"
                    android:title="@string/nav_menu_select_site" />
            </group>
        </menu>
    </item>
</group>


0

หากคำตอบที่เลือกไม่ได้ผลสำหรับคุณคุณอาจต้องการลองเพิ่มสิ่งนี้ลงไปonCreateOptionsMenuเพิ่มเติมจากนั้นให้รหัสกลุ่มที่ไม่ซ้ำกัน:

if (Build.VERSION.SDK_INT >= 28) {
    menu.setGroupDividerEnabled(true)
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.