init
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
1
app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
||||
52
app/build.gradle.kts
Normal file
@ -0,0 +1,52 @@
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
alias(libs.plugins.jetbrainsKotlinAndroid)
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
namespace = "com.example.accountbook"
|
||||
compileSdk = 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.example.accountbook"
|
||||
minSdk = 28
|
||||
targetSdk = 34
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.navigation.fragment.ktx)
|
||||
implementation(libs.androidx.navigation.ui.ktx)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
}
|
||||
21
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@ -0,0 +1,24 @@
|
||||
package com.example.accountbook
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.example.accountbook", appContext.packageName)
|
||||
}
|
||||
}
|
||||
43
app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AccountBook"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AccountBook">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.ActivityCalendar"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AccountBook">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.ActivityWriter"
|
||||
android:exported="true"
|
||||
android:theme="@style/Theme.AccountBook">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
44
app/src/main/java/com/example/accountbook/FirstFragment.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package com.example.accountbook
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.example.accountbook.databinding.FragmentFirstBinding
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
*/
|
||||
class FirstFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentFirstBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// binding.buttonFirst.setOnClickListener {
|
||||
// findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
||||
// }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
63
app/src/main/java/com/example/accountbook/MainActivity.kt
Normal file
@ -0,0 +1,63 @@
|
||||
package com.example.accountbook
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.example.accountbook.activity.ActivityCalendar
|
||||
import com.example.accountbook.databinding.ActivityMainBinding
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
appBarConfiguration = AppBarConfiguration(navController.graph)
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
|
||||
binding.fab.setOnClickListener { view ->
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null)
|
||||
.setAnchorView(R.id.fab).show()
|
||||
}
|
||||
|
||||
startActivity(Intent(applicationContext, ActivityCalendar::class.java))
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
return when (item.itemId) {
|
||||
R.id.action_settings -> true
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
return navController.navigateUp(appBarConfiguration)
|
||||
|| super.onSupportNavigateUp()
|
||||
}
|
||||
}
|
||||
44
app/src/main/java/com/example/accountbook/SecondFragment.kt
Normal file
@ -0,0 +1,44 @@
|
||||
package com.example.accountbook
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.example.accountbook.databinding.FragmentSecondBinding
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the second destination in the navigation.
|
||||
*/
|
||||
class SecondFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentSecondBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
_binding = FragmentSecondBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.buttonSecond.setOnClickListener {
|
||||
findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.example.accountbook.activity
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.accountbook.R
|
||||
import com.example.accountbook.calendar.CalendarAdapter
|
||||
import com.example.accountbook.calendar.CalendarBean
|
||||
import com.example.accountbook.calendar.CalendarDateView
|
||||
import com.example.accountbook.databinding.ActivityCalendarBinding
|
||||
import com.example.accountbook.fragment.FragmentCalendar
|
||||
import com.example.accountbook.fragment.FragmentTable
|
||||
|
||||
class ActivityCalendar: AppCompatActivity(){
|
||||
private lateinit var bind: ActivityCalendarBinding
|
||||
val fragmentCalendar: FragmentCalendar by lazy { FragmentCalendar() }
|
||||
val fragmentTable: FragmentTable by lazy { FragmentTable() }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// binding view
|
||||
bind = ActivityCalendarBinding.inflate(this.layoutInflater)
|
||||
// setting content view
|
||||
setContentView(bind.root)
|
||||
bind.chkShift.setOnClickListener() { _ ->
|
||||
// 화면 전환
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(
|
||||
R.id.fragment_box,
|
||||
if (bind.chkShift.isChecked) fragmentTable else fragmentCalendar
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(
|
||||
R.id.fragment_box, fragmentCalendar
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.example.accountbook.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.example.accountbook.R
|
||||
import com.example.accountbook.databinding.ActivityWriterBinding
|
||||
|
||||
class ActivityWriter: AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val bind = ActivityWriterBinding.inflate(this.layoutInflater)
|
||||
setContentView(bind.root)
|
||||
val adapter = ArrayAdapter<String>(this, R.layout.item_spinner_writer_category, arrayListOf("기타","식비","통신비","급여"))
|
||||
bind.spinnerWriteCategory.adapter = adapter
|
||||
bind.btnWriteClose.setOnClickListener{
|
||||
this.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.example.accountbook.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import com.example.accountbook.R
|
||||
import com.example.accountbook.databinding.ItemTableBinding
|
||||
|
||||
class AdapterTable(context: Context, private val data: Array<String>):
|
||||
ArrayAdapter<String>(context, R.layout.item_table, data) {
|
||||
private lateinit var bind:ItemTableBinding
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
var rView: View? = convertView
|
||||
if (rView == null) {
|
||||
// 최초 생성
|
||||
bind = ItemTableBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
}
|
||||
bind.textDate.text = "10/25"
|
||||
bind.textAmount.text = "10,000"
|
||||
bind.textMemo.text = "커피"
|
||||
bind.textCategory.text = "기타"
|
||||
return bind.root
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
|
||||
interface CalendarAdapter {
|
||||
fun getView(convertView: View?, parentView: ViewGroup?, bean: CalendarBean?): View
|
||||
fun hasChildView() : Boolean
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.example.accountbook.calendar;
|
||||
|
||||
public class CalendarBean {
|
||||
public int year;
|
||||
public int month;
|
||||
public int day;
|
||||
public int week;
|
||||
|
||||
//-1,0,1
|
||||
public int monthFlag;
|
||||
|
||||
//显示
|
||||
|
||||
public CalendarBean(int year, int month, int day) {
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
public String getDisplayWeek(){
|
||||
String s="";
|
||||
switch(week){
|
||||
case 1:
|
||||
s="星期日";
|
||||
break;
|
||||
case 2:
|
||||
s="星期一";
|
||||
break;
|
||||
case 3:
|
||||
s="星期二";
|
||||
break;
|
||||
case 4:
|
||||
s="星期三";
|
||||
break;
|
||||
case 5:
|
||||
s="星期四";
|
||||
break;
|
||||
case 6:
|
||||
s="星期五";
|
||||
break;
|
||||
case 7:
|
||||
s="星期六";
|
||||
break;
|
||||
|
||||
}
|
||||
return s ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String s=year+"/"+month+"/"+day;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.example.accountbook.R
|
||||
import com.example.accountbook.calendar.CalendarFactory.getMonthOfDayList
|
||||
import java.util.Date
|
||||
import java.util.LinkedList
|
||||
|
||||
|
||||
class CalendarDateView(context: Context, attrs: AttributeSet?):
|
||||
ViewPager(context, attrs), CalendarTopView {
|
||||
var views = HashMap<Int, CalendarView>()
|
||||
private var mCaledarLayoutChangeListener: CalendarTopViewChangeListener? = null
|
||||
private var onItemClickListener: CalendarView.OnItemClickListener? = null
|
||||
private val cache: LinkedList<CalendarView?> = LinkedList<CalendarView?>()
|
||||
private val MAXCOUNT = 6
|
||||
private var row = 6
|
||||
private var mAdapter: CalendarAdapter? = null
|
||||
override var itemHeight = 0
|
||||
private set
|
||||
|
||||
|
||||
fun setAdapter(adapter: CalendarAdapter?) {
|
||||
mAdapter = adapter
|
||||
initialize()
|
||||
initData()
|
||||
}
|
||||
|
||||
fun setOnItemClickListener(onItemClickListener: CalendarView.OnItemClickListener?) {
|
||||
this.onItemClickListener = onItemClickListener
|
||||
}
|
||||
|
||||
init {
|
||||
val a = context.obtainStyledAttributes(attrs, R.styleable.CalendarDateView)
|
||||
row = a.getInteger(R.styleable.CalendarDateView_cbd_calendar_row, 6)
|
||||
a.recycle()
|
||||
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
// var calendarHeight = 0
|
||||
if (adapter != null) {
|
||||
(getChildAt(0) as CalendarView)?.let {
|
||||
// calendarHeight = it.measuredHeight
|
||||
itemHeight = it.itemHeight
|
||||
}
|
||||
}
|
||||
setMeasuredDimension(
|
||||
widthMeasureSpec,
|
||||
MeasureSpec.makeMeasureSpec(heightMeasureSpec, MeasureSpec.EXACTLY)
|
||||
)
|
||||
}
|
||||
|
||||
private fun initialize() {
|
||||
val dateArr: IntArray = CalendarUtil.getYMD(Date())
|
||||
setAdapter(object : PagerAdapter() {
|
||||
override fun getCount(): Int {
|
||||
// Log.i(this@CalendarDateView::class.java.simpleName, "container >>> setAdapter getCount")
|
||||
return Int.MAX_VALUE
|
||||
}
|
||||
|
||||
override fun isViewFromObject(view: View, `object`: Any): Boolean {
|
||||
return view === `object`
|
||||
}
|
||||
|
||||
override fun instantiateItem(container: ViewGroup, position: Int): Any {
|
||||
|
||||
Log.i(this@CalendarDateView::class.java.simpleName, "container >>> ${container} position >> ${position}")
|
||||
val view: CalendarView = if (!cache.isEmpty()) {
|
||||
cache.removeFirst()!!
|
||||
} else {
|
||||
CalendarView(container.context, row)
|
||||
}
|
||||
view.setOnItemClickListener(onItemClickListener)
|
||||
view.setAdapter(mAdapter)
|
||||
|
||||
container.addView(view)
|
||||
views[position] = view
|
||||
view.apply {
|
||||
setData(
|
||||
getMonthOfDayList(
|
||||
dateArr[0],
|
||||
dateArr[1] + position - Int.MAX_VALUE / 2
|
||||
), position == Int.MAX_VALUE / 2
|
||||
)
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
|
||||
container.removeView(`object` as View)
|
||||
cache.addLast(`object` as CalendarView)
|
||||
views.remove(position)
|
||||
}
|
||||
})
|
||||
addOnPageChangeListener(object: SimpleOnPageChangeListener() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
super.onPageSelected(position)
|
||||
onItemClickListener?.let{
|
||||
views[position]?.let {v ->
|
||||
val obs: Array<Any> = v.select
|
||||
it.onItemClick(
|
||||
obs[0] as View,
|
||||
obs[1] as Int,
|
||||
obs[2] as CalendarBean
|
||||
)
|
||||
}
|
||||
}
|
||||
mCaledarLayoutChangeListener?.onLayoutChange(this@CalendarDateView)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
setCurrentItem(Int.MAX_VALUE / 2, false)
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override val currentSelectPositon: IntArray
|
||||
get() {
|
||||
var view = views[currentItem]
|
||||
if (view == null) {
|
||||
view = getChildAt(0) as? CalendarView
|
||||
}
|
||||
return view?.getSelectPosition() ?: IntArray(4)
|
||||
}
|
||||
|
||||
override fun setCalendarTopViewChangeListener(listener: CalendarTopViewChangeListener?) {
|
||||
mCaledarLayoutChangeListener = listener
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import android.util.Log
|
||||
import com.example.accountbook.calendar.CalendarUtil.getDayOfWeek
|
||||
import java.util.Calendar
|
||||
|
||||
|
||||
object CalendarFactory {
|
||||
private val cache = HashMap<String, List<CalendarBean>>()
|
||||
|
||||
fun getMonthOfDayList(y: Int, m: Int): List<CalendarBean> {
|
||||
Log.e("TIME CHECK" , "fun getMonthOfDayList Start")
|
||||
val key = y.toString() + "" + m
|
||||
if (cache.containsKey(key)) {
|
||||
val list = cache[key]
|
||||
if (list == null) {
|
||||
cache.remove(key)
|
||||
} else {
|
||||
return list
|
||||
}
|
||||
}
|
||||
val list: MutableList<CalendarBean> = ArrayList()
|
||||
cache[key] = list
|
||||
|
||||
val fweek: Int = getDayOfWeek(y, m, 1)
|
||||
val total: Int = CalendarUtil.getDayOfMaonth(y, m)
|
||||
|
||||
for (i in fweek - 1 downTo 1) {
|
||||
val bean = getCalendarBean(y, m, 1 - i)
|
||||
bean.monthFlag = -1
|
||||
list.add(bean)
|
||||
}
|
||||
|
||||
for (i in 0 until total) {
|
||||
val bean = getCalendarBean(y, m, i + 1)
|
||||
list.add(bean)
|
||||
}
|
||||
|
||||
for (i in 0 until 42 - (fweek - 1) - total) {
|
||||
val bean = getCalendarBean(y, m, total + i + 1)
|
||||
bean.monthFlag = 1
|
||||
list.add(bean)
|
||||
}
|
||||
Log.e("TIME CHECK" , "fun getMonthOfDayList END")
|
||||
return list
|
||||
}
|
||||
|
||||
fun getCalendarBean(year: Int, month: Int, day: Int): CalendarBean {
|
||||
|
||||
val calendar: Calendar = Calendar.getInstance()
|
||||
.apply { this.set(year, month - 1, day) }
|
||||
val year = calendar.get(Calendar.YEAR)
|
||||
val month = calendar.get(Calendar.MONTH) + 1
|
||||
val day = calendar.get(Calendar.DATE)
|
||||
val bean = CalendarBean(year, month, day)
|
||||
bean.week = CalendarUtil.getDayOfWeek(year, month, day)
|
||||
// val chinaDate: Array<String> = ChinaDate.getChinaDate(year, month, day)
|
||||
// bean.chinaMonth = chinaDate[0]
|
||||
// bean.chinaDay = chinaDate[1]
|
||||
return bean
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,318 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.view.VelocityTracker
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.Interpolator
|
||||
import android.widget.AbsListView
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ListView
|
||||
import androidx.core.view.VelocityTrackerCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.widget.ScrollerCompat
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
class CalendarLayout : FrameLayout {
|
||||
private var view1: View? = null
|
||||
// private var view2: ViewGroup? = null
|
||||
private var mTopView: CalendarTopView? = null
|
||||
var type = TYPE_OPEN
|
||||
|
||||
private var isSilde = false
|
||||
private var topHeigth = 0
|
||||
private var itemHeight = 0
|
||||
private var bottomViewTopHeight = 0
|
||||
private var maxDistance = 0
|
||||
private var mScroller: ScrollerCompat? = null
|
||||
private var mMaxVelocity = 0f
|
||||
private var mMinVelocity = 0f
|
||||
private var activitPotionerId = 0
|
||||
|
||||
constructor(context: Context?) : super(context!!) {
|
||||
init()
|
||||
}
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(
|
||||
context!!, attrs
|
||||
) {
|
||||
init()
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
val viewPager: CalendarTopView = getChildAt(0) as CalendarTopView
|
||||
mTopView = viewPager
|
||||
view1 = viewPager as View
|
||||
// view2 = getChildAt(1) as ViewGroup
|
||||
mTopView?.setCalendarTopViewChangeListener(object: CalendarTopViewChangeListener {
|
||||
override fun onLayoutChange(topView: CalendarTopView) {
|
||||
requestLayout()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
itemHeight = mTopView?.itemHeight ?: 0
|
||||
topHeigth = view1?.measuredHeight ?: 0
|
||||
maxDistance = topHeigth - itemHeight
|
||||
when (type) {
|
||||
TYPE_FOLD -> bottomViewTopHeight = itemHeight
|
||||
TYPE_OPEN -> bottomViewTopHeight = topHeigth
|
||||
}
|
||||
// view2!!.measure(
|
||||
// widthMeasureSpec,
|
||||
// MeasureSpec.makeMeasureSpec(
|
||||
// MeasureSpec.getSize(heightMeasureSpec) - (mTopView?.itemHeight ?: 0),
|
||||
// MeasureSpec.EXACTLY
|
||||
// )
|
||||
// )
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
// view2!!.offsetTopAndBottom(bottomViewTopHeight)
|
||||
val selectRct = selectRect
|
||||
if (type == TYPE_FOLD) {
|
||||
view1!!.offsetTopAndBottom(-selectRct[1])
|
||||
}
|
||||
}
|
||||
|
||||
private fun init() {
|
||||
val vc = ViewConfiguration.get(context)
|
||||
mMaxVelocity = vc.scaledMaximumFlingVelocity.toFloat()
|
||||
mMinVelocity = vc.scaledMinimumFlingVelocity.toFloat()
|
||||
mScroller = ScrollerCompat.create(context, sInterpolator)
|
||||
}
|
||||
|
||||
var oy = 0f
|
||||
var ox = 0f
|
||||
var isClickBtottomView = false
|
||||
// override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
||||
//// mViewDragHelper.shouldInterceptTouchEvent(ev);
|
||||
// var isflag = false
|
||||
// when (ev.action) {
|
||||
// MotionEvent.ACTION_DOWN -> {
|
||||
// oy = ev.y
|
||||
// ox = ev.x
|
||||
// isClickBtottomView = isClickView(view2, ev)
|
||||
// cancel()
|
||||
// activitPotionerId = ev.getPointerId(0)
|
||||
// val top = view2!!.top
|
||||
// type = if (top < topHeigth) {
|
||||
// TYPE_FOLD
|
||||
// } else {
|
||||
// TYPE_OPEN
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// MotionEvent.ACTION_MOVE -> {
|
||||
// val y = ev.y
|
||||
// val x = ev.x
|
||||
// val xdiff = x - ox
|
||||
// val ydiff = y - oy
|
||||
// if (abs(ydiff.toDouble()) > 5 && abs(ydiff.toDouble()) > abs(xdiff.toDouble())) {
|
||||
// isflag = true
|
||||
// if (isClickBtottomView) {
|
||||
// val isScroll = isScroll(view2)
|
||||
// if (ydiff > 0) {
|
||||
// //向下
|
||||
// if (type == TYPE_OPEN) {
|
||||
// return super.onInterceptTouchEvent(ev)
|
||||
// } else {
|
||||
// if (isScroll) {
|
||||
// return super.onInterceptTouchEvent(ev)
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// //向上
|
||||
// if (type == TYPE_FOLD) {
|
||||
// return super.onInterceptTouchEvent(ev)
|
||||
// } else {
|
||||
// if (isScroll) {
|
||||
// return super.onInterceptTouchEvent(ev)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ox = x
|
||||
// oy = y
|
||||
// }
|
||||
//
|
||||
// MotionEvent.ACTION_UP -> {}
|
||||
// }
|
||||
// return isSilde || isflag || super.onInterceptTouchEvent(ev)
|
||||
// }
|
||||
|
||||
private fun isScroll(view2: ViewGroup?): Boolean {
|
||||
val fistChildView = view2!!.getChildAt(0) ?: return false
|
||||
if (view2 is ListView) {
|
||||
val list = view2 as AbsListView
|
||||
if (fistChildView.top != 0) {
|
||||
return true
|
||||
} else {
|
||||
if (list.getPositionForView(fistChildView) != 0) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun isClickView(view: View?, ev: MotionEvent): Boolean {
|
||||
val rect = Rect()
|
||||
view!!.getHitRect(rect)
|
||||
val isClick = rect.contains(ev.x.toInt(), ev.y.toInt())
|
||||
Log.d(
|
||||
TAG,
|
||||
"isClickView() called with: isClick = [$isClick]"
|
||||
)
|
||||
return isClick
|
||||
}
|
||||
|
||||
// override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
// processTouchEvent(event)
|
||||
// return true
|
||||
// }
|
||||
|
||||
private var mVelocityTracker: VelocityTracker? = null
|
||||
// fun processTouchEvent(event: MotionEvent) {
|
||||
// if (mVelocityTracker == null) {
|
||||
// mVelocityTracker = VelocityTracker.obtain()
|
||||
// }
|
||||
// mVelocityTracker!!.addMovement(event)
|
||||
// when (event.action) {
|
||||
// MotionEvent.ACTION_DOWN -> {}
|
||||
// MotionEvent.ACTION_MOVE -> {
|
||||
// if (isSilde) {
|
||||
// return
|
||||
// }
|
||||
// val cy = event.y
|
||||
// val dy = (cy - oy).toInt()
|
||||
// if (dy == 0) {
|
||||
// return
|
||||
// }
|
||||
// oy = cy
|
||||
// move(dy)
|
||||
// }
|
||||
//
|
||||
// MotionEvent.ACTION_UP -> {
|
||||
// if (isSilde) {
|
||||
// cancel()
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// //判断速度
|
||||
// val pointerId = activitPotionerId
|
||||
// mVelocityTracker!!.computeCurrentVelocity(1000, mMaxVelocity)
|
||||
// val crrentV = VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId)
|
||||
// if (abs(crrentV.toDouble()) > 2000) {
|
||||
// if (crrentV > 0) {
|
||||
// open()
|
||||
// } else {
|
||||
// flod()
|
||||
// }
|
||||
// cancel()
|
||||
// return
|
||||
// }
|
||||
// val top = view2!!.top - topHeigth
|
||||
// val maxd = maxDistance
|
||||
// if (abs(top.toDouble()) < maxd / 2) {
|
||||
// open()
|
||||
// } else {
|
||||
// flod()
|
||||
// }
|
||||
// cancel()
|
||||
// }
|
||||
//
|
||||
// MotionEvent.ACTION_CANCEL -> cancel()
|
||||
// }
|
||||
// }
|
||||
|
||||
// fun open() {
|
||||
// startScroll(view2!!.top, topHeigth)
|
||||
// }
|
||||
//
|
||||
// fun flod() {
|
||||
// startScroll(view2!!.top, topHeigth - maxDistance)
|
||||
// }
|
||||
|
||||
private val selectRect: IntArray
|
||||
get() = mTopView?.currentSelectPositon ?: intArrayOf()
|
||||
|
||||
// private fun move(dy: Int) {
|
||||
// val selectRect = selectRect
|
||||
// val itemHeight: Int = mTopView?.itemHeight ?: 0
|
||||
// val dy1 = getAreaValue(view1!!.top, dy, -selectRect[1], 0)
|
||||
// val dy2 = getAreaValue(view2!!.top - topHeigth, dy, -(topHeigth - itemHeight), 0)
|
||||
// if (dy1 != 0) {
|
||||
// ViewCompat.offsetTopAndBottom(view1!!, dy1)
|
||||
// }
|
||||
// if (dy2 != 0) {
|
||||
// ViewCompat.offsetTopAndBottom(view2!!, dy2)
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun getAreaValue(top: Int, dy: Int, minValue: Int, maxValue: Int): Int {
|
||||
if (top + dy < minValue) {
|
||||
return minValue - top
|
||||
}
|
||||
return if (top + dy > maxValue) {
|
||||
maxValue - top
|
||||
} else dy
|
||||
}
|
||||
|
||||
private fun startScroll(starty: Int, endY: Int) {
|
||||
val distance = (endY - starty).toFloat()
|
||||
val t = distance / maxDistance * 600
|
||||
mScroller!!.startScroll(0, 0, 0, endY - starty, abs(t.toDouble()).toInt())
|
||||
postInvalidate()
|
||||
}
|
||||
|
||||
var oldY = 0
|
||||
// override fun computeScroll() {
|
||||
// super.computeScroll()
|
||||
// bottomViewTopHeight = view2!!.top
|
||||
// if (mScroller!!.computeScrollOffset()) {
|
||||
// isSilde = true
|
||||
// val cy = mScroller!!.currY
|
||||
// val dy = cy - oldY
|
||||
// move(dy)
|
||||
// oldY = cy
|
||||
// postInvalidate()
|
||||
// } else {
|
||||
// oldY = 0
|
||||
// isSilde = false
|
||||
// }
|
||||
// }
|
||||
|
||||
fun cancel() {
|
||||
if (mVelocityTracker != null) {
|
||||
mVelocityTracker!!.recycle()
|
||||
mVelocityTracker = null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CalendarLayout"
|
||||
|
||||
const val TYPE_OPEN = 0
|
||||
|
||||
const val TYPE_FOLD = 1
|
||||
private val sInterpolator: Interpolator = object: Interpolator {
|
||||
override fun getInterpolation(t: Float): Float {
|
||||
var t = t
|
||||
t -= 1.0f
|
||||
return t * t * t * t * t + 1.0f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
|
||||
interface CalendarTopView {
|
||||
val currentSelectPositon: IntArray?
|
||||
val itemHeight: Int
|
||||
|
||||
fun setCalendarTopViewChangeListener(listener: CalendarTopViewChangeListener?)
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
interface CalendarTopViewChangeListener {
|
||||
fun onLayoutChange(topView: CalendarTopView) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
|
||||
object CalendarUtil {
|
||||
fun getDayOfWeek(y: Int, m: Int, day: Int): Int {
|
||||
val calendar: Calendar = Calendar.getInstance()
|
||||
calendar.set(y, m - 1, day)
|
||||
return calendar.get(Calendar.DAY_OF_WEEK)
|
||||
}
|
||||
|
||||
//获取一月最大天数
|
||||
fun getDayOfMaonth(y: Int, m: Int): Int {
|
||||
val cal: Calendar = Calendar.getInstance()
|
||||
cal.set(y, m - 1, 1)
|
||||
return cal.getActualMaximum(Calendar.DATE)
|
||||
}
|
||||
|
||||
fun getMothOfMonth(y: Int, m: Int): Int {
|
||||
val cal: Calendar = Calendar.getInstance()
|
||||
cal.set(y, m - 1, 1)
|
||||
val dateOfMonth: Int = cal.get(Calendar.MONTH)
|
||||
return dateOfMonth + 1
|
||||
}
|
||||
|
||||
fun getYMD(date: Date?): IntArray {
|
||||
val cal: Calendar = Calendar.getInstance()
|
||||
date?.let { cal.setTime(it) }
|
||||
return intArrayOf(
|
||||
cal.get(Calendar.YEAR),
|
||||
cal.get(Calendar.MONTH) + 1,
|
||||
cal.get(Calendar.DATE)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
package com.example.accountbook.calendar
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.example.accountbook.calendar.CalendarUtil.getYMD
|
||||
import java.util.Date
|
||||
|
||||
|
||||
class CalendarView : ViewGroup {
|
||||
private var selectPosition = -1
|
||||
private var adapter: CalendarAdapter? = null
|
||||
private var data: List<CalendarBean>? = null
|
||||
private var onItemClickListener: OnItemClickListener? = null
|
||||
private var row = 6
|
||||
private val column = 7
|
||||
private var itemWidth = 0
|
||||
var itemHeight = 0
|
||||
private set
|
||||
private var isToday = false
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onItemClick(view: View?, position: Int, bean: CalendarBean?)
|
||||
}
|
||||
|
||||
constructor(context: Context?, row: Int) : super(context) {
|
||||
this.row = row
|
||||
}
|
||||
|
||||
fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
|
||||
this.onItemClickListener = onItemClickListener
|
||||
}
|
||||
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
||||
setWillNotDraw(false)
|
||||
}
|
||||
|
||||
fun setAdapter(adapter: CalendarAdapter?) {
|
||||
this.adapter = adapter
|
||||
}
|
||||
|
||||
fun setData(data: List<CalendarBean>?, isToday: Boolean) {
|
||||
this.data = data
|
||||
this.isToday = isToday
|
||||
setItem()
|
||||
requestLayout()
|
||||
}
|
||||
|
||||
private fun setItem() {
|
||||
selectPosition = -1
|
||||
if (adapter == null) {
|
||||
throw RuntimeException("adapter is null,please setadapter")
|
||||
}
|
||||
Log.i("data >>> ","data ${data}")
|
||||
if (adapter?.hasChildView() == true) {
|
||||
for (i in data!!.indices) {
|
||||
val bean = data!![i]
|
||||
val chidView: View? = adapter?.getView(
|
||||
getChildAt(i).also { v -> Log.i("data >>> ", "view $v") },
|
||||
this,
|
||||
bean
|
||||
).also { v -> Log.i("data >>> ", "chidView $v") }
|
||||
if (chidView != null && chidView != getChildAt(i)) {
|
||||
addViewInLayout(chidView, i, chidView.layoutParams, true)
|
||||
}
|
||||
if (isToday && selectPosition == -1) {
|
||||
val date = getYMD(Date())
|
||||
if (bean.year == date[0] && bean.month == date[1] && bean.day == date[2]) {
|
||||
selectPosition = i
|
||||
}
|
||||
} else {
|
||||
if (selectPosition == -1 && bean.day == 1) {
|
||||
selectPosition = i
|
||||
}
|
||||
}
|
||||
chidView?.isSelected = selectPosition == i
|
||||
setItemClick(chidView, i, bean)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val select: Array<Any>
|
||||
get() = arrayOf(
|
||||
getChildAt(selectPosition), selectPosition,
|
||||
data!![selectPosition]
|
||||
)
|
||||
|
||||
fun setItemClick(view: View?, potsion: Int, bean: CalendarBean?) {
|
||||
view?.setOnClickListener {
|
||||
if (selectPosition != -1) {
|
||||
getChildAt(selectPosition).isSelected = false
|
||||
getChildAt(potsion).isSelected = true
|
||||
}
|
||||
selectPosition = potsion
|
||||
if (onItemClickListener != null) {
|
||||
onItemClickListener!!.onItemClick(view, potsion, bean)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getSelectPosition(): IntArray {
|
||||
val rect = Rect()
|
||||
try {
|
||||
getChildAt(selectPosition).getHitRect(rect)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return intArrayOf(rect.left, rect.top, rect.right, rect.top)
|
||||
}
|
||||
|
||||
|
||||
var lastwidthMeasureSpec = 0
|
||||
var lastheightMeasureSpec = 0
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||
Log.e(this.javaClass::class.java.simpleName , "this count check ${this}")
|
||||
if (widthMeasureSpec != lastwidthMeasureSpec || heightMeasureSpec != lastheightMeasureSpec) {
|
||||
val parentWidth =
|
||||
MeasureSpec.getSize(
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
widthMeasureSpec,
|
||||
MeasureSpec.EXACTLY
|
||||
)
|
||||
)
|
||||
val parentH =
|
||||
MeasureSpec.getSize(
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
heightMeasureSpec,
|
||||
MeasureSpec.EXACTLY
|
||||
)
|
||||
)
|
||||
itemWidth = parentWidth / column
|
||||
itemHeight = parentH / row
|
||||
// itemWidth
|
||||
val view = getChildAt(0) ?: return
|
||||
val params = view.layoutParams
|
||||
if (params != null && params.height > 0) {
|
||||
itemHeight = params.height
|
||||
}
|
||||
setMeasuredDimension(parentWidth, itemHeight * row)
|
||||
if (childCount.equals(row*column))
|
||||
for (i in 0 until childCount) {
|
||||
val childView = getChildAt(i)
|
||||
childView.measure(
|
||||
MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY)
|
||||
)
|
||||
}
|
||||
}
|
||||
Log.i(
|
||||
TAG,
|
||||
"onMeasure() called with: itemHeight = [$itemHeight], itemWidth = [$itemWidth]"
|
||||
)
|
||||
lastwidthMeasureSpec = widthMeasureSpec
|
||||
lastheightMeasureSpec = heightMeasureSpec
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||
if (changed && childCount.equals(row*column))
|
||||
for (i in 0 until childCount) {
|
||||
layoutChild(getChildAt(i), i, l, t, r, b)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addViewInLayout(
|
||||
child: View?,
|
||||
index: Int,
|
||||
params: LayoutParams?,
|
||||
preventRequestLayout: Boolean
|
||||
): Boolean {
|
||||
Log.d("CalendarView, time","time")
|
||||
return super.addViewInLayout(child, index, params, preventRequestLayout)
|
||||
}
|
||||
|
||||
private fun layoutChild(view: View, position: Int, l: Int, t: Int, r: Int, b: Int) {
|
||||
var l = l
|
||||
var t = t
|
||||
var r = r
|
||||
var b = b
|
||||
val cc = position % column
|
||||
val cr = position / column
|
||||
val itemWidth = view.measuredWidth
|
||||
val itemHeight = view.measuredHeight
|
||||
l = cc * itemWidth
|
||||
t = cr * itemHeight
|
||||
r = l + itemWidth
|
||||
b = t + itemHeight
|
||||
view.layout(l, t, r, b)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CalendarView"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.example.accountbook.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.accountbook.activity.ActivityWriter
|
||||
import com.example.accountbook.calendar.CalendarAdapter
|
||||
import com.example.accountbook.calendar.CalendarBean
|
||||
import com.example.accountbook.databinding.FragmentCalendarBinding
|
||||
import com.example.accountbook.databinding.ItemCalendarBinding
|
||||
|
||||
class FragmentCalendar: Fragment() {
|
||||
private lateinit var bind: FragmentCalendarBinding
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
bind = FragmentCalendarBinding.inflate(inflater)
|
||||
return bind.root
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// init view
|
||||
if (bind.calendarDateView.adapter == null) {
|
||||
initView()
|
||||
}
|
||||
// init list
|
||||
// initList()
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
Log.i("FragmentCalendar","initView")
|
||||
|
||||
bind.calendarDateView.setAdapter(object: CalendarAdapter {
|
||||
override fun getView(
|
||||
convertView: View?,
|
||||
parentView: ViewGroup?,
|
||||
bean: CalendarBean?
|
||||
): View {
|
||||
Log.i("FragmentCalendar","getView")
|
||||
|
||||
var bindItem : ItemCalendarBinding? = null
|
||||
if (convertView == null) {
|
||||
bindItem = ItemCalendarBinding.inflate(LayoutInflater.from(parentView?.context))
|
||||
} else {
|
||||
bindItem = ItemCalendarBinding.bind(convertView)
|
||||
}
|
||||
bindItem.day.apply {
|
||||
this.text = bean?.day.toString()
|
||||
if (bean?.monthFlag != 0) {
|
||||
this.setTextColor(Color.WHITE)
|
||||
} else {
|
||||
this.setTextColor(Color.BLACK)
|
||||
}
|
||||
}
|
||||
|
||||
bindItem.root.setOnLongClickListener{ it ->
|
||||
startActivity(Intent(context, ActivityWriter::class.java))
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
return convertView ?: bindItem.root
|
||||
}
|
||||
|
||||
override fun hasChildView() = bind.calendarDateView.views.size > 0
|
||||
})
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
// private fun initList() {
|
||||
// bind.list.setAdapter(object : BaseAdapter() {
|
||||
// override fun getCount(): Int {
|
||||
// Log.i("bindList" , "getCount ")
|
||||
// return 100
|
||||
// }
|
||||
//
|
||||
// override fun getItem(position: Int) = null
|
||||
//
|
||||
// override fun getItemId(position: Int): Long = 0
|
||||
//
|
||||
// override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
// Log.i("bindList" , "getView ${position}")
|
||||
// var mConvertView: View? = convertView
|
||||
// if (mConvertView == null) {
|
||||
// mConvertView = LayoutInflater.from(this@ActivityCalendar).inflate(android.R.layout.simple_list_item_1, null)
|
||||
// }
|
||||
//
|
||||
// (mConvertView as TextView).apply {
|
||||
// this.text = "item" + position
|
||||
// this.setBackgroundColor(Color.RED)
|
||||
// }
|
||||
//
|
||||
// return mConvertView
|
||||
// }
|
||||
//
|
||||
// })
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.example.accountbook.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.accountbook.R
|
||||
import com.example.accountbook.adapter.AdapterTable
|
||||
import com.example.accountbook.databinding.FragmentTableBinding
|
||||
|
||||
class FragmentTable: Fragment() {
|
||||
private lateinit var bind: FragmentTableBinding
|
||||
private var li: Array<String> = arrayOf("0", "1")
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// view
|
||||
bind = FragmentTableBinding.inflate(inflater)
|
||||
// data
|
||||
setData()
|
||||
bind.listTable.adapter = AdapterTable(inflater.context, li)
|
||||
return bind.root
|
||||
}
|
||||
|
||||
private fun setData() {
|
||||
|
||||
}
|
||||
}
|
||||
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
182
app/src/main/res/layout/activity_calendar.xml
Normal file
@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
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:id="@+id/activity_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:background="#bbbbbb"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="0">
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp"
|
||||
android:gravity="center"
|
||||
android:text="월표시"
|
||||
android:textColor="@color/black"
|
||||
/>
|
||||
<CheckBox
|
||||
android:id="@+id/chk_shift"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="Shift"
|
||||
/>
|
||||
<!-- <Button-->
|
||||
<!-- android:id="@+id/btn_shift"-->
|
||||
<!-- android:layout_width="30dp"-->
|
||||
<!-- android:layout_height="30dp"-->
|
||||
<!-- android:text="전환"-->
|
||||
<!-- android:layout_gravity="start|center_vertical"/>-->
|
||||
<Button
|
||||
android:id="@+id/btn_menu"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:text="메뉴"
|
||||
android:layout_gravity="end|center_vertical"/>
|
||||
</FrameLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="#cccccc"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="소득"
|
||||
android:textColor="@color/black"/>
|
||||
<TextView
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="+"
|
||||
android:textColor="#ff0000"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="소득액"
|
||||
android:textColor="#ff0000"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="#cccccc"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="지출"
|
||||
android:textColor="@color/black"/>
|
||||
<TextView
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="-"
|
||||
android:textColor="#0000ff"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="지출액"
|
||||
android:textColor="#0000ff"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragment_box"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
<!-- <LinearLayout-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="28dp"-->
|
||||
<!-- android:orientation="horizontal"-->
|
||||
<!-- android:background="#dddddd"-->
|
||||
<!-- android:layout_weight="0">-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="일요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="월요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="화요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="수요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="목요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="금요일"-->
|
||||
<!-- />-->
|
||||
<!-- <TextView-->
|
||||
<!-- android:layout_width="0dp"-->
|
||||
<!-- android:layout_height="match_parent"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:text="토요일"-->
|
||||
<!-- />-->
|
||||
<!-- </LinearLayout>-->
|
||||
|
||||
<!-- <com.example.accountbook.calendar.CalendarLayout-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="0dp"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:background="#eeeeee"-->
|
||||
<!-- >-->
|
||||
<!-- <com.example.accountbook.calendar.CalendarDateView-->
|
||||
<!-- android:id="@+id/calendarDateView"-->
|
||||
<!-- android:background="#ddd000"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent"/>-->
|
||||
<!-- <ListView-->
|
||||
<!-- android:id="@+id/list"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:background="#ffffff"-->
|
||||
<!-- />-->
|
||||
<!-- </com.example.accountbook.calendar.CalendarLayout>-->
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
33
app/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.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"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="@dimen/fab_margin"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
139
app/src/main/res/layout/activity_writer.xml
Normal file
@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:padding="20dp"
|
||||
android:background="#aaaaaa">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
<TextView
|
||||
android:id="@+id/text_write_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="2024.10.17"
|
||||
android:gravity="center"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:background="@color/white"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_write_close"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:gravity="center"
|
||||
android:text="close"
|
||||
app:layout_constraintTop_toTopOf="@id/text_write_title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_write_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_write_addition_or_subtraction"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_write_title"
|
||||
android:gravity="start|center_vertical"
|
||||
android:background="@color/white">
|
||||
<RadioButton
|
||||
android:id="@+id/rb_write_addition"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="소득"/>
|
||||
<RadioButton
|
||||
android:id="@+id/rb_write_subtraction"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="지출"
|
||||
android:layout_marginStart="10dp"
|
||||
android:checked="true"/>
|
||||
</RadioGroup>
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/rg_write_addition_or_subtraction"
|
||||
android:background="@color/white">
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:outlineProvider="bounds"
|
||||
android:outlineSpotShadowColor="@color/white"
|
||||
android:outlineAmbientShadowColor="@color/black"
|
||||
android:elevation="10dp">
|
||||
<TextView
|
||||
android:id="@+id/text_write_subject_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:text="금액"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
<TextView
|
||||
android:id="@+id/text_write_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.7"
|
||||
android:text="74,000"
|
||||
android:gravity="end"
|
||||
android:paddingEnd="20dp"/>
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:outlineProvider="bounds"
|
||||
android:outlineSpotShadowColor="@color/white"
|
||||
android:outlineAmbientShadowColor="@color/black"
|
||||
android:elevation="10dp">
|
||||
<TextView
|
||||
android:id="@+id/text_write_subject_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:text="카테고리"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
<Spinner
|
||||
android:id="@+id/spinner_write_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.7"
|
||||
android:dropDownWidth="match_parent"
|
||||
android:popupBackground="@color/white"
|
||||
android:textAlignment="textEnd"/>
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:outlineProvider="bounds"
|
||||
android:outlineSpotShadowColor="@color/white"
|
||||
android:outlineAmbientShadowColor="@color/black"
|
||||
android:elevation="10dp">
|
||||
<TextView
|
||||
android:id="@+id/text_write_subject_memo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:text="메모"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
<TextView
|
||||
android:id="@+id/text_write_memo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.7"
|
||||
android:text="커피"
|
||||
android:gravity="end"
|
||||
android:paddingEnd="20dp"/>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
19
app/src/main/res/layout/content_main.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_host_fragment_content_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
82
app/src/main/res/layout/fragment_calendar.xml
Normal file
@ -0,0 +1,82 @@
|
||||
<?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="match_parent"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="28dp"
|
||||
android:orientation="horizontal"
|
||||
android:background="#dddddd"
|
||||
android:layout_weight="0">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="일요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="월요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="화요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="수요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="목요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="금요일"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="토요일"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- <com.example.accountbook.calendar.CalendarLayout-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="0dp"-->
|
||||
<!-- android:layout_weight="1"-->
|
||||
<!-- android:background="#eeeeee"-->
|
||||
<!-- >-->
|
||||
<com.example.accountbook.calendar.CalendarDateView
|
||||
android:id="@+id/calendarDateView"
|
||||
android:background="#ddd000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<!-- <ListView-->
|
||||
<!-- android:id="@+id/list"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:background="#ffffff"-->
|
||||
<!-- />-->
|
||||
<!-- </com.example.accountbook.calendar.CalendarLayout>-->
|
||||
</LinearLayout>
|
||||
44
app/src/main/res/layout/fragment_first.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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=".FirstFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- <Button-->
|
||||
<!-- android:id="@+id/button_first"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:text="@string/showing_detail"-->
|
||||
<!-- app:layout_constraintBottom_toTopOf="@id/view_calendar"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toTopOf="parent" />-->
|
||||
|
||||
<!-- <CalendarView-->
|
||||
<!-- android:id="@+id/view_calendar"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="16dp"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/button_first"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent" />-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/textview_first"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_marginTop="16dp"-->
|
||||
<!-- android:text="@string/lorem_ipsum"-->
|
||||
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
|
||||
<!-- app:layout_constraintEnd_toEndOf="parent"-->
|
||||
<!-- app:layout_constraintStart_toStartOf="parent"-->
|
||||
<!-- app:layout_constraintTop_toBottomOf="@id/button_first" />-->
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
35
app/src/main/res/layout/fragment_second.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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=".SecondFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/showing_home"
|
||||
app:layout_constraintBottom_toTopOf="@id/textview_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/lorem_ipsum"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_second" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
44
app/src/main/res/layout/fragment_table.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TableLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#33ee33">
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.1"
|
||||
android:text="날짜"
|
||||
android:gravity="center"
|
||||
android:background="#eeeeee"/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.3"
|
||||
android:text="금액"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.5"
|
||||
android:text="메모"
|
||||
android:gravity="center"
|
||||
android:background="#eeeeee"/>
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.2"
|
||||
android:text="카테고리"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
</TableRow>
|
||||
<ListView
|
||||
android:id="@+id/list_table"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
</TableLayout>
|
||||
54
app/src/main/res/layout/item_calendar.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/day"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="날짜"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_plus"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="+"
|
||||
android:textColor="#ff0000"
|
||||
app:layout_constraintTop_toBottomOf="@id/day"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="당일소득"
|
||||
android:textColor="#ff0000"
|
||||
app:layout_constraintTop_toTopOf="@id/text_plus"
|
||||
app:layout_constraintStart_toEndOf="@id/text_plus"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_plus"/>
|
||||
<TextView
|
||||
android:id="@+id/text_minus"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="-"
|
||||
android:textColor="#0000ff"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_plus"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="당일지출"
|
||||
android:textColor="#0000ff"
|
||||
app:layout_constraintTop_toTopOf="@id/text_minus"
|
||||
app:layout_constraintStart_toEndOf="@id/text_minus"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_minus"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
9
app/src/main/res/layout/item_spinner_writer_category.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<TextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="기타"
|
||||
android:gravity="end"
|
||||
/>
|
||||
37
app/src/main/res/layout/item_table.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/text_date"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.1"
|
||||
android:text="date"
|
||||
android:gravity="center"
|
||||
android:background="#eeeeee"/>
|
||||
<TextView
|
||||
android:id="@+id/text_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.3"
|
||||
android:text="amount"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
<TextView
|
||||
android:id="@+id/text_memo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.5"
|
||||
android:text="memo"
|
||||
android:gravity="center"
|
||||
android:background="#eeeeee"/>
|
||||
<TextView
|
||||
android:id="@+id/text_category"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.2"
|
||||
android:text="category"
|
||||
android:gravity="center"
|
||||
android:background="#dddddd"/>
|
||||
</TableRow>
|
||||
10
app/src/main/res/menu/menu_main.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<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="com.example.accountbook.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
6
app/src/main/res/mipmap-anydpi/ic_launcher.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
6
app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
28
app/src/main/res/navigation/nav_graph.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation 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:id="@+id/nav_graph"
|
||||
app:startDestination="@id/FirstFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/FirstFragment"
|
||||
android:name="com.example.accountbook.FirstFragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_FirstFragment_to_SecondFragment"
|
||||
app:destination="@id/SecondFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/SecondFragment"
|
||||
android:name="com.example.accountbook.SecondFragment"
|
||||
android:label="@string/second_fragment_label"
|
||||
tools:layout="@layout/fragment_second">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_SecondFragment_to_FirstFragment"
|
||||
app:destination="@id/FirstFragment" />
|
||||
</fragment>
|
||||
</navigation>
|
||||
3
app/src/main/res/values-land/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
7
app/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.AccountBook" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
</style>
|
||||
</resources>
|
||||
9
app/src/main/res/values-v23/themes.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<style name="Theme.AccountBook" parent="Base.Theme.AccountBook">
|
||||
<!-- Transparent system bars for edge-to-edge. -->
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
|
||||
</style>
|
||||
</resources>
|
||||
3
app/src/main/res/values-w1240dp/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">200dp</dimen>
|
||||
</resources>
|
||||
3
app/src/main/res/values-w600dp/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
9
app/src/main/res/values/attr.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="cbd_calendar_row" format="integer"/>
|
||||
|
||||
<declare-styleable name="CalendarDateView">
|
||||
<attr name="cbd_calendar_row"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
5
app/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
3
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
46
app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<resources>
|
||||
<string name="app_name">AccountBook</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<!-- Strings used for fragments for navigation -->
|
||||
<string name="first_fragment_label">First Fragment</string>
|
||||
<string name="second_fragment_label">Second Fragment</string>
|
||||
<string name="showing_detail">상세 보기</string>
|
||||
<string name="showing_home">홈으로</string>
|
||||
|
||||
<string name="lorem_ipsum">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris
|
||||
volutpat, dolor id interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus
|
||||
dui nec risus. Maecenas non sodales nisi, vel dictum dolor. Class aptent taciti sociosqu ad
|
||||
litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse blandit eleifend
|
||||
diam, vel rutrum tellus vulputate quis. Aliquam eget libero aliquet, imperdiet nisl a,
|
||||
ornare ex. Sed rhoncus est ut libero porta lobortis. Fusce in dictum tellus.\n\n
|
||||
Suspendisse interdum ornare ante. Aliquam nec cursus lorem. Morbi id magna felis. Vivamus
|
||||
egestas, est a condimentum egestas, turpis nisl iaculis ipsum, in dictum tellus dolor sed
|
||||
neque. Morbi tellus erat, dapibus ut sem a, iaculis tincidunt dui. Interdum et malesuada
|
||||
fames ac ante ipsum primis in faucibus. Curabitur et eros porttitor, ultricies urna vitae,
|
||||
molestie nibh. Phasellus at commodo eros, non aliquet metus. Sed maximus nisl nec dolor
|
||||
bibendum, vel congue leo egestas.\n\n
|
||||
Sed interdum tortor nibh, in sagittis risus mollis quis. Curabitur mi odio, condimentum sit
|
||||
amet auctor at, mollis non turpis. Nullam pretium libero vestibulum, finibus orci vel,
|
||||
molestie quam. Fusce blandit tincidunt nulla, quis sollicitudin libero facilisis et. Integer
|
||||
interdum nunc ligula, et fermentum metus hendrerit id. Vestibulum lectus felis, dictum at
|
||||
lacinia sit amet, tristique id quam. Cras eu consequat dui. Suspendisse sodales nunc ligula,
|
||||
in lobortis sem porta sed. Integer id ultrices magna, in luctus elit. Sed a pellentesque
|
||||
est.\n\n
|
||||
Aenean nunc velit, lacinia sed dolor sed, ultrices viverra nulla. Etiam a venenatis nibh.
|
||||
Morbi laoreet, tortor sed facilisis varius, nibh orci rhoncus nulla, id elementum leo dui
|
||||
non lorem. Nam mollis ipsum quis auctor varius. Quisque elementum eu libero sed commodo. In
|
||||
eros nisl, imperdiet vel imperdiet et, scelerisque a mauris. Pellentesque varius ex nunc,
|
||||
quis imperdiet eros placerat ac. Duis finibus orci et est auctor tincidunt. Sed non viverra
|
||||
ipsum. Nunc quis augue egestas, cursus lorem at, molestie sem. Morbi a consectetur ipsum, a
|
||||
placerat diam. Etiam vulputate dignissim convallis. Integer faucibus mauris sit amet finibus
|
||||
convallis.\n\n
|
||||
Phasellus in aliquet mi. Pellentesque habitant morbi tristique senectus et netus et
|
||||
malesuada fames ac turpis egestas. In volutpat arcu ut felis sagittis, in finibus massa
|
||||
gravida. Pellentesque id tellus orci. Integer dictum, lorem sed efficitur ullamcorper,
|
||||
libero justo consectetur ipsum, in mollis nisl ex sed nisl. Donec maximus ullamcorper
|
||||
sodales. Praesent bibendum rhoncus tellus nec feugiat. In a ornare nulla. Donec rhoncus
|
||||
libero vel nunc consequat, quis tincidunt nisl eleifend. Cras bibendum enim a justo luctus
|
||||
vestibulum. Fusce dictum libero quis erat maximus, vitae volutpat diam dignissim.
|
||||
</string>
|
||||
</resources>
|
||||
9
app/src/main/res/values/themes.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.AccountBook" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.AccountBook" parent="Base.Theme.AccountBook" />
|
||||
</resources>
|
||||
13
app/src/main/res/xml/backup_rules.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
19
app/src/main/res/xml/data_extraction_rules.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
17
app/src/test/java/com/example/accountbook/ExampleUnitTest.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package com.example.accountbook
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
15
build.gradle.kts
Normal file
@ -0,0 +1,15 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication) apply false
|
||||
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.jakewharton:butterknife-gradle-plugin:10.2.3")
|
||||
}
|
||||
}
|
||||
23
gradle.properties
Normal file
@ -0,0 +1,23 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. For more details, visit
|
||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
89
gradlew.bat
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
24
settings.gradle.kts
Normal file
@ -0,0 +1,24 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google {
|
||||
content {
|
||||
includeGroupByRegex("com\\.android.*")
|
||||
includeGroupByRegex("com\\.google.*")
|
||||
includeGroupByRegex("androidx.*")
|
||||
}
|
||||
}
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "AccountBook"
|
||||
include(":app")
|
||||
|
||||