Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีทำ SlidingDrawer เลื่อนจากด้านซ้ายใน Android

ภาพรวม

บทความนี้สาธิตวิธาสร้าง Drawer ที่เลื่อนออกมาจากด้านซ้าย (Left Sidebar/Navigation Drawer) ใน Android หมายเหตุ: SlidingDrawer ถูก Deprecated แล้วตั้งแต่ API 17 ควรใช้ DrawerLayout (จาก AndroidX) หรือ NavigationView แทน ซึ่งเป็นมาตรฐานปัจจุบัน

วิธีเก่า: SlidingDrawer (Deprecated - ไม่แนะนำ)

โค้ดต้นฉบับใช้ SlidingDrawer พร้อม Rotation Hack ซึ่งไม่เสถียรและไม่รองรับ Material Design

วิธีใหม่: DrawerLayout + NavigationView (แนะนำ - Modern Standard)

ขั้นตอนที่ 1: Dependencies (build.gradle)

dependencies {
    implementation "androidx.drawerlayout:drawerlayout:1.2.0"
    implementation "com.google.android.material:material:1.11.0"
}

ขั้นตอนที่ 2: Layout หลัก (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <!-- Main Content -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

        <FrameLayout
            android:id="@+id/contentFrame"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <!-- Navigation Drawer (Left Side) -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

ขั้นตอนที่ 3: Drawer Header (res/layout/drawer_header.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:orientation="vertical"
    android:padding="16dp"
    android:gravity="bottom"
    android:background="?attr/colorPrimary"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:src="@mipmap/ic_launcher_round"
        android:contentDescription="Profile" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="User Name"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="user@example.com"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" />

</LinearLayout>

ขั้นตอนที่ 4: Drawer Menu (res/menu/drawer_menu.xml)

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

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_home"
            android:title="หน้าแรก" />
        <item
            android:id="@+id/nav_profile"
            android:icon="@drawable/ic_person"
            android:title="โปรไฟล์" />
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_settings"
            android:title="การตั้งค่า" />
    </group>

    <item android:title="อื่นๆ">
        <menu>
            <item
                android:id="@+id/nav_about"
                android:icon="@drawable/ic_info"
                android:title="เกี่ยวกับ" />
            <item
                android:id="@+id/nav_logout"
                android:icon="@drawable/ic_logout"
                android:title="ออกจากระบบ" />
        </menu>
    </item>

</menu>

ขั้นตอนที่ 5: MainActivity.java

import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.material.navigation.NavigationView;

public class MainActivity extends AppCompatActivity 
        implements NavigationView.OnNavigationItemSelectedListener {

    private DrawerLayout drawerLayout;
    private NavigationView navigationView;
    private ActionBarDrawerToggle toggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Toolbar
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // DrawerLayout
        drawerLayout = findViewById(R.id.drawerLayout);
        navigationView = findViewById(R.id.navigationView);
        navigationView.setNavigationItemSelectedListener(this);

        // Hamburger Icon + Animation
        toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        );
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();

        // Default Selection
        if (savedInstanceState == null) {
            navigationView.setCheckedItem(R.id.nav_home);
            loadFragment(new HomeFragment());
        }
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        int id = item.getItemId();
        
        if (id == R.id.nav_home) {
            loadFragment(new HomeFragment());
        } else if (id == R.id.nav_profile) {
            loadFragment(new ProfileFragment());
        } else if (id == R.id.nav_settings) {
            loadFragment(new SettingsFragment());
        } else if (id == R.id.nav_about) {
            Toast.makeText(this, "About", Toast.LENGTH_SHORT).show();
        } else if (id == R.id.nav_logout) {
            // Handle logout
        }

        drawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    private void loadFragment(androidx.fragment.app.Fragment fragment) {
        getSupportFragmentManager().beginTransaction()
            .replace(R.id.contentFrame, fragment)
            .commit();
    }
}

ขั้นตอนที่ 6: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

การปรับแต่งเพิ่มเติม (Customization)

1. เปลี่ยนความกว้าง Drawer


android:layout_width="280dp" 

DrawerLayout.LayoutParams params = (DrawerLayout.LayoutParams) navigationView.getLayoutParams();
params.width = (int) (getResources().getDisplayMetrics().widthPixels * 0.8f);
navigationView.setLayoutParams(params);

2. Right Drawer (ด้านขวา)

<NavigationView
    android:layout_gravity="end" 
    ... />

// เปิด/ปิดด้านขวา
drawerLayout.openDrawer(GravityCompat.END);
drawerLayout.closeDrawer(GravityCompat.END);

3. Lock/Unlock Drawer

// ล็อกไม่ให้เปิดได้
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
// ปลดล็อก
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

4. Custom Drawer (ไม่ใช้ NavigationView)

<DrawerLayout ...>
    <!-- Content -->
    <LinearLayout ...>...</LinearLayout>

    <!-- Custom Left Drawer -->
    <LinearLayout
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:orientation="vertical"
        android:background="@android:color/white">
        <!-- ใส่ View ใดๆ ได้ -->
    </LinearLayout>
</DrawerLayout>

สรุปการเปลี่ยนจาก SlidingDrawer

SlidingDrawer (Deprecated)DrawerLayout (Current)
Single Direction (Top/Bottom/Left/Right)Start/End (รองรับ RTL อัตโนมัติ)
ต้องใช้ Rotation Hackไม่ต้อง Hack รองรับ Native
ไม่มี Material Designรองรับ Material Design เต็มรูปแบบ
ไม่มี NavigationViewมี NavigationView + Menu Resource
ไม่รองรับ Toolbar Animationมี ActionBarDrawerToggle (Hamburger ↔ Arrow)
API 17+ DeprecatedAndroidX Support ทุก Version