반응형

오늘은 코틀린(Kotlin)을 사용해서 파일 탐색기 만들기에 경로 확인 ToolBar을 추가해보겠습니다.

파일 탐색기를 사용해서 파일을 이동하면 현재 위치를 알 수 없는 단점을 보안하기 위해서 상단에 ToolBar를 사용해서 현재 경로를 저장할 수 있는 로직을 구현해보겠습니다.

먼저 ToolBar에 적용하기 위한 layout을 생성합니다.

layout 하단에 item_file_breadcrumb.xml 파일을 생성합니다.

Android 버전에 따라서 ConstraintLayout는 패키지 정보를 수정해야 합니다.

수정을 안할 경우 실행 시 App이 바로 종료되는 문제가 발생합니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
    android:layout_height="wrap_content"
    android:background="?selectableItemBackgroundBorderless"
    android:padding="8dp">

    <ImageView
        android:id="@+id/arrowTextView"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:src="@drawable/ic_folder_dark_24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:tint="@color/grey"/>

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="4dp"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@id/arrowTextView"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Pictures" />

</androidx.constraintlayout.widget.ConstraintLayout>

ToolBar는 이미지를 출력하기 위한 ImageView 및 경로를 출력하기 위한 TextView로 구성해줍니다.

ImageView에 사용할 이미지를 Vector을 사용해서 추가합니다.

VectorDrawable는 정적 드로어블 객체로 path 및 group 객체로 구성할 수 있습니다.

https://developer.android.com/guide/topics/graphics/vector-drawable-resources?hl=ko 

 

벡터 드로어블 개요  |  Android 개발자  |  Android Developers

이 문서에서는 프레임워크 API 또는 지원 라이브러리를 통해 벡터 드로어블 리소스의 전반적인 사용을 설명합니다.

developer.android.com

drawable 하단에 ic_right_black_24dp.xml을 추가합니다.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

vector을 사용해서 path를 구성합니다.

색상을 추가하기 위해서 colors.xml에 grey를 추가합니다.

이번에는 모든 경로를 확인하기 위한 RecyclerView.Adapter를 확장한 BreadcrumbFileAdapter 클래스를 생성합니다.

class BreadcrumbFileAdapter : RecyclerView.Adapter<BreadcrumbFileAdapter.ViewHolder>() {

    var onItemClickListener: ((FileModel) -> Unit)? = null

    var files = listOf<FileModel>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_file_breadcrumb, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount() = files.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) = holder.bindView(position)

    fun updateData(files: List<FileModel>) {
        this.files = files
        notifyDataSetChanged()
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

        init {
            itemView.setOnClickListener(this)
        }

        override fun onClick(v: View?) {
            onItemClickListener?.invoke(files[adapterPosition])
        }

        fun bindView(position: Int) {
            val file = files[position]
            itemView.nameTextView.text = file.name
        }
    }
}

사용자가 선택한 파일 목록을 업데이트 하기 위해서 클래스 내부에 있는 RecyclerView.Adapter를 사용합니다.

이제 경로를 확인하기 위한 layout을 activity_main.xml에 추가합니다.

<com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="@string/app_name"
            app:titleTextColor="@color/grey">

        </androidx.appcompat.widget.Toolbar>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/breadcrumbRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        </androidx.recyclerview.widget.RecyclerView>

    </com.google.android.material.appbar.AppBarLayout>

Toolbar widget를 사용하기 위해서 AppBarLayout를 사용합니다.

최신 Android 버전에서는 패키지가 변경되어 패키지 수정이 필요합니다.

패키지 오류가 발생할 경우 아래 사이트를 확인해주세요.

https://believecom.tistory.com/750?category=1109462 

 

android How to solve ' java.lang.ClassNotFoundException: Didn't find class "com.google.android.material.appbar.AppBarLayout"'

Android에서 AppBarLayout을 추가하면 컴파일에는 문제가 없지만 실행 시점 오류가 발생합니다. 오류 내용은 'java.lang.ClassNotFoundException: Didn't find class "com.google.android.material.appbar.Ap..

believecom.tistory.com

정상적으로 소스를 추가 했다면 아래 화면을 확인할 수 있습니다.

상단에 텍스트가 추가된 ToolBar가 적용되어 있습니다.

파일 탐색기를 사용하면 다양하게 이동할 수 있기 때문에 모든 이벤트 내용을 저장해서 위치를 확인해야 합니다.

모든 내용을 저장하기 위해서 BackStackManager 클래스를 생성하겠습니다.

main 패키지 하단에 BackStackManager.kt를 추가해주세요.

class BackStackManager {
    private var files = mutableListOf<FileModel>()
    var onStackChangeListener: ((List<FileModel>) -> Unit)? = null

    val top: FileModel
        get() = files[files.size - 1]

    fun addToStack(fileModel: FileModel) {
        files.add(fileModel)
        onStackChangeListener?.invoke(files)
    }

    fun popFromStack() {
        if (files.isNotEmpty())
            files.removeAt(files.size - 1)
        onStackChangeListener?.invoke(files)
    }

    fun popFromStackTill(fileModel: FileModel) {
        files = files.subList(0, files.indexOf(fileModel) + 1)
        onStackChangeListener?.invoke(files)
    }
}

BackStackManager 클래스는 3개의 함수로 운영됩니다.

files 변수를 사용해서 파일 이동 경로를 저장합니다.

onStackChangeListener 이벤트를 사용해서 수진 정보를 확인합니다.

top 변수는 최상단 파일 정보를 리턴하게 적용합니다.

이제 BackStackManager을 적용하기 위해서 MainActivity로 이동합니다.

backStackManager 변수를 선언 합니다.

 private fun initViews() {
        setSupportActionBar(toolbar)

        breadcrumbRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
        mBreadcrumbFileAdapter = BreadcrumbFileAdapter()
        breadcrumbRecyclerView.adapter = mBreadcrumbFileAdapter
        mBreadcrumbFileAdapter.onItemClickListener = {
            supportFragmentManager.popBackStack(it.path, 2);
            backStackManager.popFromStackTill(it)
        }
    }
    private fun initBackStack(){
        backStackManager.onStackChangeListener = {
            updateAdapterData(it)
        }
        backStackManager.addToStack(fileModel = FileModel(Environment.getExternalStorageDirectory().absolutePath, FileType.FOLDER, "/", 0.0))
    }
    
    private fun updateAdapterData(files:List<FileModel>){
        mBreadcrumbFileAdapter.updateData(files)
        if(files.isNotEmpty()){
            breadcrumbRecyclerView.smoothScrollToPosition(files.size - 1)
        }
    }

toolbar 및 backStack를 초기화하기 위한 initViews(), InitBackStack() 함수를 생성합니다.

InitViews() 함수는 처음에 생성한 BreadcrumbFileAdapter을 사용해서 layout View에 연동합니다.

initBackStack() 함수는 BackStackManager가 동작할 경우 업데이트를 실행합니다.

이제 마지막으로 폴더를 선택할 경우 backStackManager를 연동해서 파일 정보를 업데이트합니다.

AddFileFragment(), onBackPressed() 함수에  backStackManager 클래스 메서드를 호출합니다.

이제 파일 탐색기에서 폴더를 이동하면 상단에 폴더 경로를 한눈에 확인할 수 있습니다.

폴더 경로 정보는 매우 단순한 내용처럼 보이지만 파일 이동에 따른 중요한 요소입니다.

오늘은 파일 탐색기 4번째 시간으로 파일 경로를 추가했습니다.

감사합니다.

http://thetechnocafe.com/build-a-file-explorer-in-kotlin-part-4-adding-breadcrumbs/

 

Build a File Explorer in Kotlin – Part 4 – Adding Breadcrumbs - TheTechnoCafe

In this File Explorer tutorial you will add the functionality which enables the user to navigate back to any position in the backstack.

thetechnocafe.com

 

반응형

+ Recent posts