...
This commit is contained in:
parent
996a75fc3e
commit
a8c7641e69
@ -6,17 +6,22 @@ import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
@ -64,6 +69,14 @@ class NaturalOrderComparator : Comparator<File> {
|
||||
}
|
||||
}
|
||||
|
||||
enum class RenameMode(val label: String) {
|
||||
REPLACE("문자열 제거/치환"),
|
||||
TRUNCATE_AFTER("기준 문자열 이후 제거 (앞 남기기)"),
|
||||
TRUNCATE_BEFORE("기준 문자열 이전 제거 (뒤 남기기)"), // 💡 추가
|
||||
BATCH_NUMBERING("전체 변경 + 넘버링"),
|
||||
SEQUENTIAL("순차적 직접 변경")
|
||||
}
|
||||
|
||||
class CompletedFilesFragment : Fragment() {
|
||||
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
@ -77,7 +90,7 @@ class CompletedFilesFragment : Fragment() {
|
||||
private var currentSort = FileSortType.NAME
|
||||
private var currentViewMode = FileViewMode.LIST_TEXT
|
||||
private var isDescending = true
|
||||
|
||||
private var searchQuery = "" // 💡 실시간 검색어 저장용 변수
|
||||
// 💡 멀티 선택 모드 상태 관리 변수
|
||||
private var isSelectionMode = false
|
||||
private val selectedFiles = mutableSetOf<File>()
|
||||
@ -403,15 +416,59 @@ class CompletedFilesFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
private fun setupControls(view: View) {
|
||||
val layoutTitleDefault = view.findViewById<View>(R.id.layoutTitleDefault)
|
||||
val layoutTitleSearch = view.findViewById<View>(R.id.layoutTitleSearch)
|
||||
val etSearch = view.findViewById<EditText>(R.id.etSearch)
|
||||
val btnSearch = view.findViewById<TextView>(R.id.btnSearch)
|
||||
val btnCloseSearch = view.findViewById<TextView>(R.id.btnCloseSearch)
|
||||
val spinnerFilter = view.findViewById<Spinner>(R.id.spinnerFilter)
|
||||
val spinnerSort = view.findViewById<Spinner>(R.id.spinnerSort)
|
||||
val tvSortOrder = view.findViewById<TextView>(R.id.tvSortOrder)
|
||||
val btnViewMode = view.findViewById<TextView>(R.id.btnViewMode)
|
||||
val btnOrganize = view.findViewById<TextView>(R.id.btnOrganize)
|
||||
// 💡 검색 모드 진입
|
||||
btnSearch.setOnClickListener {
|
||||
layoutTitleDefault.visibility = View.GONE
|
||||
layoutTitleSearch.visibility = View.VISIBLE
|
||||
etSearch.requestFocus()
|
||||
// 키보드 보이기 로직(선택사항)
|
||||
etSearch.postDelayed({ // 뷰가 완전히 그려진 후 키보드를 띄우기 위해 약간의 지연 실행
|
||||
val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.showSoftInput(etSearch, InputMethodManager.SHOW_IMPLICIT)
|
||||
}, 100)
|
||||
|
||||
}
|
||||
view.findViewById<View>(R.id.tvTitle)?.setOnClickListener { btnSearch.performClick() }
|
||||
|
||||
// 💡 검색 모드 종료
|
||||
btnCloseSearch.setOnClickListener {
|
||||
searchQuery = ""
|
||||
etSearch.setText("")
|
||||
layoutTitleDefault.visibility = View.VISIBLE
|
||||
layoutTitleSearch.visibility = View.GONE
|
||||
applyFilterAndSort() // 리스트 복구
|
||||
}
|
||||
|
||||
// 💡 실시간 타이핑 감지
|
||||
etSearch.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
searchQuery = s.toString()
|
||||
applyFilterAndSort() // 텍스트 바뀔 때마다 즉시 필터링
|
||||
}
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
})
|
||||
|
||||
// 💡 선택 액션 바 버튼 이벤트
|
||||
view.findViewById<View>(R.id.btnSelectAll)?.setOnClickListener {
|
||||
selectedFiles.clear()
|
||||
selectedFiles.addAll(adapter.getAll())
|
||||
adapter.updateSelection(selectedFiles)
|
||||
}
|
||||
|
||||
view.findViewById<View>(R.id.btnCancelSelection)?.setOnClickListener { toggleSelectionMode(false) }
|
||||
view.findViewById<View>(R.id.btnMoveSelected)?.setOnClickListener { showMoveDialog() }
|
||||
view.findViewById<View>(R.id.btnRenameSelected)?.setOnClickListener { showBatchRenameDialog() }
|
||||
view.findViewById<View>(R.id.btnDeleteSelected)?.setOnClickListener {
|
||||
if (selectedFiles.isEmpty()) return@setOnClickListener
|
||||
android.app.AlertDialog.Builder(requireContext())
|
||||
@ -495,6 +552,188 @@ class CompletedFilesFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun renamePrefsEntry(oldName: String, newName: String) {
|
||||
val prefs = requireContext().getSharedPreferences("FileAccessTracker", Context.MODE_PRIVATE)
|
||||
|
||||
// 1. 기존 데이터 가져오기
|
||||
val lastAccessed = prefs.getLong(oldName, 0L)
|
||||
val accessCount = prefs.getInt("${oldName}_count", 0)
|
||||
|
||||
// 2. 새 이름으로 데이터 저장 및 기존 데이터 삭제
|
||||
if (lastAccessed != 0L || accessCount != 0) {
|
||||
prefs.edit().apply {
|
||||
// 새 키로 복사
|
||||
putLong(newName, lastAccessed)
|
||||
putInt("${newName}_count", accessCount)
|
||||
// 기존 키 삭제
|
||||
remove(oldName)
|
||||
remove("${oldName}_count")
|
||||
apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateNewName(file: File, mode: RenameMode, in1: String, in2: String, index: Int): String {
|
||||
val extension = file.extension
|
||||
val fileNameOnly = file.nameWithoutExtension
|
||||
|
||||
return when (mode) {
|
||||
RenameMode.REPLACE -> {
|
||||
// 특정 문자열 제거(in2가 비어있을 때) 또는 치환
|
||||
fileNameOnly.replace(in1, in2) + if (extension.isNotEmpty()) ".$extension" else ""
|
||||
}
|
||||
RenameMode.TRUNCATE_AFTER -> {
|
||||
// 예: "P2024_이미지.jpg"에서 "_" 기준 이후 제거 -> "P2024.jpg"
|
||||
val idx = fileNameOnly.indexOf(in1)
|
||||
if (idx != -1) fileNameOnly.substring(0, idx) + if (extension.isNotEmpty()) ".$extension" else ""
|
||||
else file.name
|
||||
}
|
||||
RenameMode.TRUNCATE_BEFORE -> {
|
||||
// 💡 예: "P2024_이미지.jpg"에서 "_" 기준 이전 제거 -> "이미지.jpg"
|
||||
val idx = fileNameOnly.indexOf(in1)
|
||||
if (idx != -1) {
|
||||
// 키워드 자체도 지우고 싶다면 idx + in1.length 부터 시작
|
||||
fileNameOnly.substring(idx + in1.length) + if (extension.isNotEmpty()) ".$extension" else ""
|
||||
} else file.name
|
||||
}
|
||||
RenameMode.BATCH_NUMBERING -> {
|
||||
// 전체 네이밍 + 넘버링 (예: 여행_01.jpg)
|
||||
"${in1}_${String.format("%02d", index)}" + if (extension.isNotEmpty()) ".$extension" else ""
|
||||
}
|
||||
RenameMode.SEQUENTIAL -> {
|
||||
// 이 모드는 다이얼로그에서 하나씩 입력받는 구조로 별도 처리가 필요할 수 있음
|
||||
"순차변경 대기중"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSequentialRename(files: List<File>, index: Int) {
|
||||
if (index >= files.size) {
|
||||
toggleSelectionMode(false)
|
||||
loadFiles()
|
||||
return
|
||||
}
|
||||
|
||||
val file = files[index]
|
||||
val et = EditText(requireContext()).apply {
|
||||
setText(file.name)
|
||||
setSelection(file.nameWithoutExtension.length) // 이름 부분만 드래그/포커스
|
||||
}
|
||||
|
||||
android.app.AlertDialog.Builder(requireContext())
|
||||
.setTitle("이름 직접 수정 (${index + 1}/${files.size})")
|
||||
.setView(et)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("다음") { _, _ ->
|
||||
val oldName = file.name
|
||||
val newName = et.text.toString()
|
||||
val dest = File(file.parentFile, newName)
|
||||
|
||||
if (oldName != newName && file.renameTo(dest)) {
|
||||
// 💡 프리퍼런스 키 업데이트
|
||||
renamePrefsEntry(oldName, newName)
|
||||
}
|
||||
showSequentialRename(files, index + 1)
|
||||
}
|
||||
.setNeutralButton("건너뛰기") { _, _ -> showSequentialRename(files, index + 1) }
|
||||
.setNegativeButton("중단", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showBatchRenameDialog() {
|
||||
val files = selectedFiles.toList().sortedWith(NaturalOrderComparator())
|
||||
if (files.isEmpty()) return
|
||||
|
||||
val view = layoutInflater.inflate(R.layout.dialog_batch_rename, null)
|
||||
val spinner = view.findViewById<Spinner>(R.id.spinnerRenameMode)
|
||||
val et1 = view.findViewById<EditText>(R.id.etInput1)
|
||||
val et2 = view.findViewById<EditText>(R.id.etInput2)
|
||||
val tvPreview = view.findViewById<TextView>(R.id.tvRenamePreview)
|
||||
|
||||
// 모드 리스트 세팅
|
||||
spinner.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, RenameMode.values().map { it.label })
|
||||
|
||||
// 실시간 미리보기 업데이트 함수
|
||||
val updateUI = {
|
||||
val mode = RenameMode.values()[spinner.selectedItemPosition]
|
||||
val preview = files.take(3).mapIndexed { i, f ->
|
||||
"${f.name} → ${generateNewName(f, mode, et1.text.toString(), et2.text.toString(), i + 1)}"
|
||||
}.joinToString("\n")
|
||||
tvPreview.text = "미리보기(최대 3개):\n$preview"
|
||||
}
|
||||
|
||||
var tWatcher = object : TextWatcher {
|
||||
override fun beforeTextChanged(
|
||||
s: CharSequence?,
|
||||
start: Int,
|
||||
count: Int,
|
||||
after: Int
|
||||
) {
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override fun onTextChanged(
|
||||
s: CharSequence?,
|
||||
start: Int,
|
||||
before: Int,
|
||||
count: Int
|
||||
) {
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
// 리스너 등록
|
||||
et1.addTextChangedListener(tWatcher)
|
||||
et2.addTextChangedListener(tWatcher)
|
||||
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, pos: Int, p3: Long) {
|
||||
val mode = RenameMode.values()[pos]
|
||||
// 모드별 가이드 UI 조정
|
||||
et1.visibility = if (mode == RenameMode.SEQUENTIAL) View.GONE else View.VISIBLE
|
||||
et2.visibility = if (mode == RenameMode.REPLACE) View.VISIBLE else View.GONE
|
||||
et1.hint = when(mode) {
|
||||
RenameMode.REPLACE -> "찾을 문자열"
|
||||
RenameMode.TRUNCATE_AFTER, RenameMode.TRUNCATE_BEFORE -> "기준 문자열"
|
||||
RenameMode.BATCH_NUMBERING -> "새 파일명 공통 부분"
|
||||
else -> ""
|
||||
}
|
||||
updateUI()
|
||||
}
|
||||
override fun onNothingSelected(p0: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
android.app.AlertDialog.Builder(requireContext())
|
||||
.setTitle("${files.size}개 파일 이름 변경")
|
||||
.setView(view)
|
||||
.setPositiveButton("적용") { _, _ ->
|
||||
val mode = RenameMode.values()[spinner.selectedItemPosition]
|
||||
if (mode == RenameMode.SEQUENTIAL) {
|
||||
showSequentialRename(files, 0)
|
||||
} else {
|
||||
var count = 0
|
||||
files.forEachIndexed { i, file ->
|
||||
val oldName = file.name
|
||||
val newName = generateNewName(file, mode, et1.text.toString(), et2.text.toString(), i + 1)
|
||||
val dest = File(file.parentFile, newName)
|
||||
|
||||
if (oldName != newName && !dest.exists() && file.renameTo(dest)) {
|
||||
// 💡 파일명이 성공적으로 바뀌었을 때 프리퍼런스 정보도 갱신
|
||||
renamePrefsEntry(oldName, newName)
|
||||
count++
|
||||
}
|
||||
}
|
||||
Toast.makeText(context, "$count 개 파일 이름 변경 완료", Toast.LENGTH_SHORT).show()
|
||||
toggleSelectionMode(false)
|
||||
loadFiles()
|
||||
}
|
||||
}
|
||||
.setNegativeButton("취소", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun organizeRootFiles() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
// 1. 루트 폴더의 파일 목록 가져오기
|
||||
@ -572,9 +811,27 @@ class CompletedFilesFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun applyFilterAndSort() {
|
||||
val folders = allFiles.filter { it.isDirectory }
|
||||
var files = allFiles.filter { it.isFile }
|
||||
// 💡 1. 데이터 소스 결정
|
||||
val baseFiles = if (searchQuery.isNotEmpty()) {
|
||||
// 검색어가 있으면 rootDir부터 모든 하위 파일/폴더를 가져옴 (Recursive)
|
||||
rootDir.walkTopDown().toList()
|
||||
} else {
|
||||
// 검색어가 없으면 현재 폴더(currentDir)의 파일만 대상으로 함
|
||||
allFiles
|
||||
}
|
||||
|
||||
// 2. 폴더와 파일 분리 및 검색어 필터링
|
||||
var folders = baseFiles.filter { it.isDirectory }
|
||||
var files = baseFiles.filter { it.isFile }
|
||||
|
||||
if (searchQuery.isNotEmpty()) {
|
||||
// 파일명에 검색어가 포함된 것만 추출 (ignoreCase로 대소문자 무시)
|
||||
files = files.filter { it.name.contains(searchQuery, ignoreCase = true) }
|
||||
// 검색 모드일 때는 폴더 결과는 제외하거나 원하면 아래 주석 해제
|
||||
folders = emptyList()
|
||||
}
|
||||
|
||||
// 3. 기존 카테고리 필터 적용 (IMAGE, VIDEO 등)
|
||||
files = files.filter { file ->
|
||||
val ext = file.extension.lowercase()
|
||||
when (currentFilter) {
|
||||
@ -586,6 +843,7 @@ class CompletedFilesFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 정렬 로직 (기존 동일)
|
||||
val naturalComparator = NaturalOrderComparator()
|
||||
val sortedFolders = folders.sortedWith(naturalComparator)
|
||||
val sortedFiles = when (currentSort) {
|
||||
@ -596,8 +854,14 @@ class CompletedFilesFragment : Fragment() {
|
||||
FileSortType.NAME -> if (isDescending) files.sortedWith(naturalComparator.reversed()) else files.sortedWith(naturalComparator)
|
||||
}
|
||||
|
||||
// 5. 최종 리스트 구성
|
||||
val finalItems = mutableListOf<File>()
|
||||
if (currentDir.absolutePath != rootDir.absolutePath) finalItems.add(File(currentDir, ".."))
|
||||
|
||||
// 💡 검색 중이 아닐 때만 "상위 폴더(..)" 아이템을 추가
|
||||
if (searchQuery.isEmpty() && currentDir.absolutePath != rootDir.absolutePath) {
|
||||
finalItems.add(File(currentDir, ".."))
|
||||
}
|
||||
|
||||
finalItems.addAll(sortedFolders)
|
||||
finalItems.addAll(sortedFiles)
|
||||
|
||||
@ -654,6 +918,8 @@ class CompletedFilesAdapter(
|
||||
|
||||
// 💡 어댑터 내부에 선택된 파일 정보 저장
|
||||
private var selectedFiles: Set<File> = emptySet()
|
||||
fun getAll() = fileList
|
||||
|
||||
|
||||
fun submitList(files: List<File>) {
|
||||
fileList = files
|
||||
|
||||
51
app/src/main/res/layout/dialog_batch_rename.xml
Normal file
51
app/src/main/res/layout/dialog_batch_rename.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="변경 모드 선택"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#888888"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/spinnerRenameMode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@android:drawable/btn_dropdown"
|
||||
android:spinnerMode="dropdown" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInput1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="입력 1"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etInput2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="입력 2"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvRenamePreview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#F5F5F5"
|
||||
android:padding="12dp"
|
||||
android:text="미리보기 결과가 여기에 표시됩니다."
|
||||
android:textColor="#555555"
|
||||
android:textSize="13sp"
|
||||
android:lineSpacingExtra="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@ -4,28 +4,69 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="?android:attr/windowBackground">
|
||||
<LinearLayout
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutTitleDefault"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="다운로드 보관함"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:padding="16dp"/>
|
||||
<TextView
|
||||
android:id="@+id/btnOrganize"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="auto_awesome" />
|
||||
</LinearLayout>
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="다운로드 보관함"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:padding="16dp"/>
|
||||
<TextView
|
||||
android:id="@+id/btnSearch"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="search" />
|
||||
<TextView
|
||||
android:id="@+id/btnOrganize"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="auto_awesome" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutTitleSearch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone">
|
||||
<EditText
|
||||
android:id="@+id/etSearch"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="파일명 키워드 검색..."
|
||||
android:background="@null"
|
||||
android:padding="16dp"
|
||||
android:singleLine="true"
|
||||
android:imeOptions="actionSearch"/>
|
||||
<TextView
|
||||
android:id="@+id/btnCloseSearch"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="close" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -34,50 +75,43 @@
|
||||
android:paddingHorizontal="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnViewMode"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="view_headline" />
|
||||
|
||||
<Space
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/spinnerFilter"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:spinnerMode="dropdown"
|
||||
/>
|
||||
|
||||
android:spinnerMode="dropdown" />
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/spinnerSort"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:spinnerMode="dropdown"
|
||||
/>
|
||||
|
||||
android:spinnerMode="dropdown" />
|
||||
<TextView
|
||||
android:id="@+id/tvSortOrder"
|
||||
style="@style/MaterialIconButtonStyle"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:text="arrow_downward" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerViewCompletedFiles"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutSelectionActions"
|
||||
android:layout_width="match_parent"
|
||||
@ -86,7 +120,15 @@
|
||||
android:background="#EEEEEE"
|
||||
android:padding="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnSelectAll"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="전체"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"/>
|
||||
<TextView
|
||||
android:id="@+id/btnCancelSelection"
|
||||
android:layout_width="0dp"
|
||||
@ -96,7 +138,15 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnRenameSelected"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="이름 변경"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"/>
|
||||
<TextView
|
||||
android:id="@+id/btnMoveSelected"
|
||||
android:layout_width="0dp"
|
||||
@ -106,7 +156,6 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:padding="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnDeleteSelected"
|
||||
android:layout_width="0dp"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user