BottomAppBar 자바로 구현하기

업데이트:

Bottom App Bars

BottomAppBar의 사용법에 대해 알아보겠습니다. 상단에 고정 되어 있는 Toolbar의 영역을, 화면 공간으로 대체하여, 위쪽 공간을 효율적으로 사용 할 수 있는 MATERIAL DESIGN의 주요 feature 입니다.

특징으로는 FAB(FloatingActionButton)과 함께 사용하며, FAB는 다음 화면으로 전환시, Back Button으로 사용 할 수 있습니다. 애니메이션이 나름 ios 같으며, 하단에 Bar가 있으므로, Bottom Sheets으로 Option Menu or Navigation Views를 대체 합니다.

Usage

MainActivity.java는 Activity로 생성하고, 화면 전환하는 View는 Fragment로 생성하였다. 일반적으로 appbar는 AndroidManifest에서 선언하는데, 이렇게 되면 BottomAppBar의 fab 애니메이션 적용이 안되서 인지, 선언이 되지 않았다. 결론은 BottomAppBar는 화면 전환 시, BottomAppBar를 detach 하고, fab를 이동 시킨 후, 다시 BottomAppBar를 붙혀야 하는 과정을 거친다.

[MainActivity.java]

package com.exam.bottomappbar;

import android.os.Bundle;
import android.os.Handler;
import android.support.design.bottomappbar.BottomAppBar;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.exam.bottomappbar.Fragment.HomeFragment;
import com.exam.bottomappbar.Fragment.PlusButtonFragment;

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();
    private FragmentTransaction transaction = null;
    private FloatingActionButton fabs = null;
    private BottomAppBar bottomAppBar;

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

        fabs = (FloatingActionButton) findViewById(R.id.fabs);

        if (savedInstanceState == null) {
            transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.flContainerHome, HomeFragment.newInstance());
            transaction.commit();
        }

        fabs.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (bottomAppBar.getFabAlignmentMode() == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER) {
                    fabs.setImageResource(R.drawable.baseline_reply_white_24);
                    transaction = getSupportFragmentManager().beginTransaction();
                    transaction.addToBackStack(HomeFragment.class.getSimpleName());
                    transaction.add(R.id.flContainerHome, PlusButtonFragment.newInstance());
                    transaction.commit();
                    detachFab();
                    moveToDetails();
                } else {
                    fabs.setImageResource(R.drawable.baseline_add_white_24);
                    detachFab();
                    returnToHome();
                    onBackPressed();
                }
            }
        });
        bottomAppBar = findViewById(R.id.bottom_appbar);
        setSupportActionBar(bottomAppBar);
        bottomAppBar.replaceMenu(R.menu.my_menu);
    }

    public void detachFab() {
        bottomAppBar.setFabAttached(false);
    }

    public void moveToDetails() {
        bottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_END);
        attachFab();
    }

    public void returnToHome() {
        bottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_CENTER);
        attachFab();
        if (bottomAppBar.getFabAlignmentMode() == BottomAppBar.FAB_ALIGNMENT_MODE_CENTER) {
            fabs.setImageResource(R.drawable.baseline_add_white_24);
        }
    }

    public void attachFab() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                bottomAppBar.setFabAttached(true);
            }
        }, 150);
    }

    @Override
    public void onBackPressed() {
        detachFab();
        returnToHome();
        super.onBackPressed();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.my_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        switch (itemId) {
            case R.id.next_btn:
                Toast.makeText(this, "next_btn", Toast.LENGTH_SHORT).show();
                //bottomSheetDialog.show(getSupportFragmentManager(),"bottomSheet");
                return true;
            case R.id.action_settings:
                Toast.makeText(this, "action_settings", Toast.LENGTH_SHORT).show();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

MainActivity에는 FrameLayout을 배치 하였고, 이곳에서 HomeFragment로 transaction 시킨다. 또한 차례로 BottomAppBar와 FloatingActionButton를 배치한다.

[activity_main.xml]

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.exam.bottomappbar.MainActivity">

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

    <android.support.design.bottomappbar.BottomAppBar
        android:id="@+id/bottom_appbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_gravity="bottom"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:fabAttached="true"
        app:backgroundTint="@color/colorPrimary"
        app:fabCradleVerticalOffset="12dp"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabs"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:src="@android:drawable/ic_input_add"
        app:layout_anchor="@+id/bottom_appbar"/>

</android.support.design.widget.CoordinatorLayout>


build.gradle(Module:app)에는 BottomAppBar 사용을 위해, 아래의 내용을 implementation 한다.

implementation 'com.android.support:design:28.0.0-alpha1'

Output

참조 된 소스는, 아래의 뷰 구성이 가능 합니다. Main 화면

source

전체 소스 : GitHub

카테고리:

업데이트: