diff --git a/CalrendarView/src/main/java/com/example/calrendarview/Adapter/PagerAdapter.kt b/CalrendarView/src/main/java/com/example/calrendarview/Adapter/PagerAdapter.kt new file mode 100644 index 0000000..6496d34 --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/Adapter/PagerAdapter.kt @@ -0,0 +1,48 @@ +package com.example.calrendarview.Adapter + +import android.os.Build +import android.util.Log +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout.LayoutParams +import androidx.annotation.RequiresApi +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.RecyclerView +import com.example.calrendarview.MonthLayout +import com.example.calrendarview.model.CalendarFactory +import com.example.calrendarview.model.CalendarPod +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.O) +class PagerAdapter( + private val pods: ArrayList, + private val idLayout: Int, + private val idTextViewNumOfDay: Int +): RecyclerView.Adapter() { + inner class ViewHolder(val view: View): RecyclerView.ViewHolder(view) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerAdapter.ViewHolder { + val container = ConstraintLayout(parent.context).apply { + this.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT) + } + return ViewHolder(container) + } + + override fun onBindViewHolder(holder: PagerAdapter.ViewHolder, position: Int) { + val container = holder.view as ViewGroup + val a = MonthLayout(holder.view.context).apply { + this.layoutParams = ConstraintLayout.LayoutParams(LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT) + this.idLayout = this@PagerAdapter.idLayout + this.idTextViewNumOfDay = this@PagerAdapter.idTextViewNumOfDay + this.listOfBean = CalendarFactory().getBeansOfMonth(pods[position]) + this.targetYear = pods[position].year + this.targetMonth = pods[position].month + } + container.removeAllViews() + container.addView(a) + Log.d("holder >>>>>","holder ${holder.view.height}, ${holder.view.width}") + } + + override fun getItemCount(): Int = pods.size +} \ No newline at end of file diff --git a/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomLayout.kt b/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomLayout.kt new file mode 100644 index 0000000..715cfd6 --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomLayout.kt @@ -0,0 +1,70 @@ +package com.example.calrendarview + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.children + +abstract class BaseCustomLayout : ConstraintLayout { + constructor(context: Context) : super(context){applyAttrs(context,null)} + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs){applyAttrs(context,attrs)} + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ){applyAttrs(context,attrs)} + + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) {applyAttrs(context,attrs)} + + + protected val tag = this:: class.simpleName + // 하루가 표시될 layout id + var idLayout : Int = -1 + // 날짜(num)가 표시될 TextView + var textViewNumOfDay : TextView? = null + // 날짜(num)가 표시될 TextView 의 id + var idTextViewNumOfDay : Int = -1 + set(value) { + field = value + Log.e(tag, "idTextViewNumOfDay $field") + } + + + private fun applyAttrs(context: Context?, attrs: AttributeSet?) { + context?.let { + onTypedArray(it, it.obtainStyledAttributes(attrs, R.styleable.BaseCustomLayout)) + } + } + + open fun onTypedArray(context: Context, typedArray : TypedArray) { + Log.e(tag, "context (${context})") + idLayout = typedArray.getResourceId(R.styleable.BaseCustomLayout_item_layout, R.layout.item_day).also { + Log.e(tag, "idLayout default (${R.layout.item_day})") + Log.e(tag, "idLayout (${idLayout}) Id >>>> ${it}") + } + idTextViewNumOfDay = typedArray.getResourceId(R.styleable.BaseCustomLayout_numOfDayId, R.id.day_num).also { + Log.e(tag, "idTextViewNumOfDay default (${R.id.day_num})") + Log.e(tag, "idTextViewNumOfDay (${idTextViewNumOfDay}) Id >>>> ${it}") + } + initLayout(context) + } + + open fun initLayout(context: Context?) { +// createdLayout(LayoutInflater.from(context).inflate(idLayout, this, true)) + } + + open fun createdLayout(view : View) { + Log.e(tag,"Created view is $view") + } +} diff --git a/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomViews.kt b/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomViews.kt deleted file mode 100644 index e3fef20..0000000 --- a/CalrendarView/src/main/java/com/example/calrendarview/BaseCustomViews.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.example.calrendarview - -import android.content.Context -import android.content.res.TypedArray -import android.util.AttributeSet -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout - -abstract class BaseCustomViews : ConstraintLayout { - protected val TAG = this:: class.simpleName - constructor(context: Context) : super(context){appyAttrs(context,null)} - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs){appyAttrs(context,attrs)} - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( - context, - attrs, - defStyleAttr - ){appyAttrs(context,attrs)} - - constructor( - context: Context, - attrs: AttributeSet?, - defStyleAttr: Int, - defStyleRes: Int - ) : super(context, attrs, defStyleAttr, defStyleRes) {appyAttrs(context,attrs)} - - var layouId : Int = -1 - open fun appyAttrs(context: Context?, attrs: AttributeSet?) { - context?.let { - onTypedArray(it,it.obtainStyledAttributes(attrs, R.styleable.BaseCustomViews)) - } - } - - open fun onTypedArray(context: Context, typedArray : TypedArray) { - layouId = typedArray.getResourceId(R.styleable.BaseCustomViews_item_layout,R.layout.item_day) - initLayout(context) - } - - fun initLayout(context: Context?) { - createdLayout(LayoutInflater.from(context).inflate(layouId, this, true)) - } - - open fun createdLayout(view : View) { - Log.e(this::class.simpleName,"view si $view") - } - -// override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { -// if (changed) { -// -// } -// } -} diff --git a/CalrendarView/src/main/java/com/example/calrendarview/CalendarLayout.kt b/CalrendarView/src/main/java/com/example/calrendarview/CalendarLayout.kt new file mode 100644 index 0000000..e52bd16 --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/CalendarLayout.kt @@ -0,0 +1,77 @@ +package com.example.calrendarview + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.os.Build +import android.util.AttributeSet +import android.util.Log +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.annotation.RequiresApi +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.viewpager2.widget.ViewPager2 +import com.example.calrendarview.Adapter.PagerAdapter +import com.example.calrendarview.model.CalendarBean +import com.example.calrendarview.model.CalendarFactory +import com.example.calrendarview.model.CalendarPod +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.O) +class CalendarLayout: BaseCustomLayout { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { + this.attrs = attrs + this.defStyleAttr = defStyleAttr + this.defStyleRes = defStyleRes + } + + var attrs: AttributeSet? = null + var defStyleAttr: Int? = null + var defStyleRes: Int? = null + private lateinit var pager: ViewPager2 + private var pods: ArrayList = arrayListOf() + + + // Constraint Layout + override fun onAttachedToWindow() { + super.onAttachedToWindow() + // Create a pager + pager = createPager() + // Attach a pager + this.removeAllViews() + this.addView(pager) + // Set pager's adapter + // Set data + setData(LocalDate.now()) + pager.adapter = PagerAdapter(pods, idLayout, idTextViewNumOfDay) + pager.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + Log.d(tag, "pager width = ${pager.measuredWidth}") + Log.d(tag, "pager height = ${pager.measuredHeight}") + } + + override fun requestLayout() { + super.requestLayout() + Log.e(tag, "did requestLayout") + } + + + // fun + fun createPager(): ViewPager2 = ViewPager2(context).apply { + this.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + orientation = ViewPager2.ORIENTATION_HORIZONTAL + } + + private fun setData(date: LocalDate) { + pods.add(CalendarPod(2024, 11)) + pods.add(CalendarPod(LocalDate.now())) + pods.add(CalendarPod(2025, 1)) + } +} \ No newline at end of file diff --git a/CalrendarView/src/main/java/com/example/calrendarview/DayLayout.kt b/CalrendarView/src/main/java/com/example/calrendarview/DayLayout.kt new file mode 100644 index 0000000..fd93481 --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/DayLayout.kt @@ -0,0 +1,76 @@ +package com.example.calrendarview + +import android.content.Context +import android.content.res.TypedArray +import android.graphics.Canvas +import android.util.AttributeSet +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.core.view.children +import com.example.calrendarview.model.DayInfo + +class DayLayout : BaseCustomLayout { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + constructor( + context: Context, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) + + + // data + private var infoDay: DayInfo? = null + + + // Constraint Layout ----------------------------------------- + // size + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + } + + // location + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + + } + + override fun onDraw(canvas: Canvas) { + super.draw(canvas) + } + + override fun requestLayout() { + super.requestLayout() + onBindInfo() + } + // ----------------------------------------------------------- + + // BaseCustomLayout ------------------------------------------ + override fun initLayout(context: Context?) { + super.initLayout(context) + val view = LayoutInflater.from(context).inflate(idLayout, this, true) + (view as? ViewGroup)?.let { + it.children.forEach { Log.e(tag,"child is ${it}") } + } + textViewNumOfDay = findViewById(idTextViewNumOfDay).also { + Log.e(tag, "textViewNumOfDay $textViewNumOfDay >>> ${it}") + } + } + // ----------------------------------------------------------- + + + private fun onBindInfo() { + textViewNumOfDay?.text = infoDay?.getNumOfDay()?.toString() ?: "TEST" + Log.e(tag, "textViewNumOfDay >>>> 4 ${textViewNumOfDay}") + Log.e(tag, "textViewNumOfDay?.text >>>> 4 ${textViewNumOfDay?.text}") + } +} diff --git a/CalrendarView/src/main/java/com/example/calrendarview/DayView.kt b/CalrendarView/src/main/java/com/example/calrendarview/DayView.kt deleted file mode 100644 index 6fbaca6..0000000 --- a/CalrendarView/src/main/java/com/example/calrendarview/DayView.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.example.calrendarview - -import android.content.Context -import android.content.res.TypedArray -import android.graphics.Canvas -import android.graphics.Color -import android.util.AttributeSet -import android.util.Log -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.core.view.children -import com.example.calrendarview.model.DayInfo - -class DayView : BaseCustomViews { - - constructor(context: Context) : super(context) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( - context, - attrs, - defStyleAttr - ) - - constructor( - context: Context, - attrs: AttributeSet?, - defStyleAttr: Int, - defStyleRes: Int - ) : super(context, attrs, defStyleAttr, defStyleRes) - - var dayInfo: DayInfo? = null - set(value) { - field = value - displayDayNumber() - } - - var numOfDayView : TextView? = null - var numberOfday : Int = -1 - set(value) { - Log.e(TAG, "numOfDayView 2 (${R.id.day_num}) Id >>>> ${value}") - field = value - numOfDayView = findViewById(field) - Log.e(TAG, "numOfDayView >>>> 3 ${numOfDayView}") - } - -// override fun appyAttrs(context: Context?, attrs: AttributeSet?) { -// context?.let { -// Log.e(TAG, "numOfDayView >>>> ${numOfDayView}") -// var typedArray = it.obtainStyledAttributes(attrs, R.styleable.BaseCustomViews) -// layouId = typedArray.getResourceId(R.styleable.BaseCustomViews_item_layout,R.layout.item_day).apply { -// Log.e(TAG, "layouId 0 (${R.layout.item_day} Id >>>> ${this}") -// } -// initLayout(context) -// -// } -// } - - override fun onTypedArray(context: Context, typedArray: TypedArray) { - super.onTypedArray(context, typedArray) - numberOfday = typedArray.getResourceId(R.styleable.BaseCustomViews_numOfDayId, R.id.day_num).apply { - Log.e(TAG, "numOfDayView 1 (${R.id.day_num}) Id >>>> ${this}") - } - displayDayNumber() - } - - override fun createdLayout(view: View) { - super.createdLayout(view) - (view as? ViewGroup)?.let { - it.children.forEach { Log.e(TAG,"child is ${it}") } - } - } - - fun displayDayNumber() { - numOfDayView?.text = dayInfo?.getNumOfDay()?.toString() ?: "TEST" - Log.e(TAG, "numOfDayView?.text >>>> 4 ${numOfDayView?.text}") - } - - fun displayDayOfWeek() { - //todo 오늘의 요일을 표시? - } - - fun isToday() : Boolean { - return false - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - Log.e(TAG,"View >>> ${this}") - } - -// override fun draw(canvas: Canvas) { -// super.draw(canvas) -// canvas.drawColor(Color.CYAN) -// } - -} diff --git a/CalrendarView/src/main/java/com/example/calrendarview/MonthLayout.kt b/CalrendarView/src/main/java/com/example/calrendarview/MonthLayout.kt new file mode 100644 index 0000000..a5e250e --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/MonthLayout.kt @@ -0,0 +1,285 @@ +package com.example.calrendarview + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.os.Build +import android.util.AttributeSet +import android.util.Log +import android.util.TypedValue +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.children +import androidx.core.view.contains +import androidx.viewpager2.widget.ViewPager2 +import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL +import androidx.viewpager2.widget.ViewPager2.Orientation +import com.example.calrendarview.Adapter.PagerAdapter +import com.example.calrendarview.model.CalendarBean +import com.example.calrendarview.model.CalendarFactory +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.O) +class MonthLayout: BaseCustomLayout { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + + + private var isInitializing: Boolean = false + private var listDayView: ArrayList = arrayListOf() + private val numberOfRow : Int = 7 + private val numberOfWeek : Int = 6 + var listOfBean: Array = arrayOf() + private var listHeaderView: ArrayList = arrayListOf() + private var isShowingHeader: Boolean = true + private var heightOfHeader: Int = 50 + var targetYear: Int = 0 + var targetMonth: Int = 0 + private var titleView: View? = null + private var heightOfTitle: Int = 100 + private var header: LinearLayout? = null + + + + // Constraint Layout ----------------------------------------------------- + override fun onAttachedToWindow() { + super.onAttachedToWindow() + this.removeAllViews() + // Make data +// setData(LocalDate.now()) + Log.d(tag, "listOfBean.size ${listOfBean.size}") + // Create view for title + createTitle() + // Create view for day of week + createHeader() + Log.e(tag, "listHeaderView.size ${listHeaderView.size}") + // Create day views and add. + Log.e(tag, "idLayout ${idLayout}") + createdDayView() + Log.d(tag, "listDayView.size ${listDayView.size}") + // Bind day views with data + if (listDayView.isNotEmpty()) { + for (i in 0 until listDayView.size) { + bindWidthData(listDayView[i], listOfBean[i]) + } + } + } + + // size + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + isInitializing = true + val selfW = MeasureSpec.getSize(widthMeasureSpec) + val selfH = MeasureSpec.getSize(heightMeasureSpec) + Log.d(tag, "selfW, selfH => ${selfW} ,${selfH}") + // Set size of view for day of week + Log.d(tag, "header measuredW, measuredH => ${header?.measuredWidth} ,${header?.measuredHeight}") + listHeaderView.forEachIndexed { _, view -> +// view.layoutParams = LayoutParams(selfW/numberOfRow, heightOfHeader) + Log.d(tag, "header view child measuredW, measuredH => ${view.measuredWidth} ,${view.measuredHeight}") + } + // Set size of day views + listDayView.forEachIndexed { _, view -> +// view.layoutParams = LayoutParams(selfW/numberOfRow, (selfH - (if (isShowingHeader) heightOfHeader else 0) - heightOfTitle)/numberOfWeek) + val headerH = if (isShowingHeader) heightOfHeader else 0 + val titleH = titleView?.measuredHeight ?: 0 + val w = selfW/numberOfRow + val h = (selfH - titleH - headerH)/numberOfWeek + view.measure(w, h) + Log.d(tag, "day view measuredW, measuredH => ${view.measuredWidth} ,${view.measuredHeight}") + } + // title view + Log.d(tag, "title view measuredW, measuredH => ${titleView?.measuredWidth} ,${titleView?.measuredHeight}") + isInitializing = false + } + + // location + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + // Locate Title view +// locatedTitleView() + // Locate view for day of week + locatedHeaderView(listHeaderView) + // Locate day views + locatedDayView(listDayView) + + requestLayout() + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + } + + override fun requestLayout() { + if (isInitializing) { + return + } + super.requestLayout() + Log.e(tag, "did requestLayout") + } + + + // fun + private fun setData(date: LocalDate) { + listOfBean = arrayOf() + listOfBean = CalendarFactory().getBeansOfThisMonth() + targetYear = LocalDate.now().year + targetMonth = LocalDate.now().monthValue + } + + private fun createdDayView() { + Log.d(tag, "on createdDayView") + isInitializing = true + // create and add to listDayView + listDayView.clear() + for (i in 0 until numberOfRow * numberOfWeek) { + listDayView.add((LayoutInflater.from(context).inflate(idLayout, this, false) as ViewGroup)) + } + // add children + listDayView.forEach { + this.addView(it) + } + isInitializing = false + } + + + private fun bindWidthData(view: ViewGroup, bean: CalendarBean) { + textViewNumOfDay = view.findViewById(idTextViewNumOfDay).apply { + this.text = bean.getNumOfDay().toString() + if (targetMonth != bean.getMonth()) { + this.setTextColor(Color.parseColor("#cccccc")) + view.children.forEach {c -> + if (c != this) { + c.visibility = GONE + } + } + } + } + } + + fun createTitle() { + if (titleView != null) { + titleView = null + } + titleView = TextView(context).apply { + this.id + this.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, heightOfTitle) + this.text = "$targetYear $targetMonth" + this.textSize = 18f + this.gravity = Gravity.CENTER + this.setBackgroundColor(Color.parseColor("#99ffff")) + } + this.addView(titleView) + } + + fun createHeader() { + +// if(header == null) { + header = LinearLayout(context).apply { + this.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, heightOfHeader) + this.orientation = ORIENTATION_HORIZONTAL + } + this.addView(header) +// } + + // 주간 요일 표시 + for (i in 0 until numberOfRow) { + Log.d(this@MonthLayout.tag, "getDayOfWeek ${listOfBean[i].getDayOfWeek()}") + TextView(context).apply { + this.layoutParams = LinearLayout.LayoutParams(0, heightOfHeader, 1f) + this.text = listOfBean[i].getDayOfWeek() + this.textSize = 8f + this.gravity = Gravity.CENTER + this.setBackgroundColor(Color.parseColor("#eeeeee")) + listHeaderView.add(this) + }.run { + header!!.addView(this) + } + } + } + + + + fun locatedTitleView() { + isInitializing = true + titleView?.let { + it.layout( + this.x.toInt(), + this.y.toInt(), + this.x.toInt() + it.measuredWidth, + this.y.toInt() + it.measuredHeight + ) + Log.d(tag, "locatedTitleView s = ${this.x.toInt()}") + Log.d(tag, "locatedTitleView t = ${this.y.toInt()}") + Log.d(tag, "locatedTitleView e = ${this.x.toInt() + it.measuredWidth}") + Log.d(tag, "locatedTitleView b = ${this.y.toInt() + it.measuredHeight}") + } + isInitializing = false + } + + fun locatedHeaderView(list: ArrayList) { + var mutableX = this.x.toInt() + val mutableY = this.y.toInt() + val headerH = if (isShowingHeader) heightOfHeader else 0 + isInitializing = true + header?.let{ + it.layout( + mutableX, + mutableY + (titleView?.measuredHeight ?: 0), + mutableX + it.measuredWidth, + mutableY + (titleView?.measuredHeight ?: 0) + it.measuredHeight + ) + } + list.forEach { + if (header?.contains(it) ?: false && + it.visibility != GONE) { + Log.d(tag, "Header s, t => ${header!!.x}, ${header!!.y}") + Log.d(tag, "Header e, b => ${header!!.x + header!!.measuredWidth}, ${header!!.y + header!!.measuredHeight}") + Log.d(tag, "locatedHeaderView s, t => ${it.x}, ${it.y}") + Log.d(tag, "locatedHeaderView e, b => ${it.x + it.measuredWidth}, ${it.y + it.measuredHeight}") + } + } + isInitializing = false + } + + private fun locatedDayView(list: ArrayList) { + var mutableX = this.x.toInt() + val headerH = if (isShowingHeader) heightOfHeader else 0 + val titleH = titleView?.measuredHeight ?: 0 + var mutableY = this.y.toInt() + headerH + titleH + Log.e(tag, "locatedDayView mutableX, mutableY ${this.x.toInt()}, ${this.y.toInt()}") + val w = this.measuredWidth/numberOfRow + val h = (this.measuredHeight - titleH - headerH)/numberOfWeek + isInitializing = true + list.forEachIndexed { i, it -> + if (this.contains(it) && + it.visibility != GONE) { + if (i % numberOfRow == 0 && + i != 0) { + mutableX = this.x.toInt() + mutableY += h + } + Log.e(tag, "locatedDayView x y ${mutableX}, ${mutableY + headerH + titleH}") + Log.e(tag, "locatedDayView r e ${mutableX + w}, ${mutableY + h}") + it.layout( + mutableX, + mutableY, + mutableX + w, + mutableY + h + ) + mutableX += w + Log.e(tag, "locatedDayView x y ${it.x}, ${it.y}") + Log.e(tag, "locatedDayView r e ${it.x + it.measuredWidth}, ${it.y + it.measuredHeight}") + } + } + isInitializing = false + } +} \ No newline at end of file diff --git a/CalrendarView/src/main/java/com/example/calrendarview/MonthView.kt b/CalrendarView/src/main/java/com/example/calrendarview/MonthView.kt deleted file mode 100644 index e1be6df..0000000 --- a/CalrendarView/src/main/java/com/example/calrendarview/MonthView.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.example.calrendarview - -import android.content.Context -import android.content.res.TypedArray -import android.os.Build -import android.util.AttributeSet -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.annotation.RequiresApi -import androidx.core.view.size -import com.example.calrendarview.model.CalendarFactory -import com.example.calrendarview.model.DayInfo - -@RequiresApi(Build.VERSION_CODES.O) -class MonthView : BaseCustomViews { - constructor(context: Context) : super(context) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) - - - override fun appyAttrs(context: Context?, attrs: AttributeSet?) { - super.appyAttrs(context, attrs) - } - - var numberOfRow : Int = 7 - set(value) { - field = value - } - - var dayInfo: DayInfo? = null - set(value) { - field = value - displayDayNumber() - } - - var numberOfday : Int = -1 - set(value) { - field = value - numOfDayView = findViewById(field) - } - var itemLayout : Int = -1 - set(value) { - field = value - } - - var numOfDayView : TextView? = null - - var mWidth: Int? = null - var mHeight: Int? = null - - - override fun onTypedArray(context: Context, typedArray: TypedArray) { - super.onTypedArray(context, typedArray) - numberOfday = typedArray.getResourceId(R.styleable.BaseCustomViews_numOfDayId, R.id.day_num) - itemLayout = typedArray.getResourceId(R.styleable.BaseCustomViews_item_layout, R.id.day_num) - displayDayNumber() - } - - override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { - super.onLayout(changed, left, top, right, bottom) - Log.i("MonthView >>> ","onLayout") - initChildViews() - } - - fun initChildViews(): Array { - //todo : 7 * numberOfRow 의 차일드 뷰를 만든다. - val infos = CalendarFactory().getBeansOfThisWeek() - val childrens = Array(numberOfRow) {i -> - val dayView = LayoutInflater.from(context).inflate(layouId, this, false) - val p = ViewGroup.LayoutParams(100, 100) - Log.i("MonthView >>> ","numberOfRow ${numberOfRow}") - dayView?.let { - it.layoutParams = p - Log.i("MonthView >>> ","dayView.width ${dayView.width}") - numOfDayView?.text = infos[i].getNumOfDay().toString() - addView(it) - } - return@Array dayView - } - Log.i("MonthView initChildViews >>> ","childrens count ${childrens.size}") - Log.i("MonthView initChildViews >>> ","mWidth ${width}") - Log.i("MonthView initChildViews >>> ","mHeight ${height}") - return childrens - } - - fun displayDayNumber() { - numOfDayView?.text = dayInfo?.getNumOfDay()?.toString() ?: "TEST" - Log.e(TAG, "numOfDayView?.text >>>> 4 ${numOfDayView?.text}") - } - - fun displyMonthOfNumber() { - //todo :월 표시 - } - - fun displayWeekHeader() { - //todo 주간 요일 표시 - } - - fun displayYear(){ - //todo 년도 표시 - } - - fun setData(days : Collection) { - //todo 최대 7*6의 데이터를 받는다. - } -} - diff --git a/CalrendarView/src/main/java/com/example/calrendarview/WeekLayout.kt b/CalrendarView/src/main/java/com/example/calrendarview/WeekLayout.kt new file mode 100644 index 0000000..85660fc --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/WeekLayout.kt @@ -0,0 +1,188 @@ +package com.example.calrendarview + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.os.Build +import android.util.AttributeSet +import android.util.Log +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.annotation.RequiresApi +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.children +import androidx.core.view.contains +import androidx.core.view.forEach +import androidx.core.view.get +import com.example.calrendarview.model.CalendarBean +import com.example.calrendarview.model.CalendarFactory +import com.example.calrendarview.model.DayInfo +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.O) +class WeekLayout : BaseCustomLayout { + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + + + // view + private val numberOfRow : Int = 7 + private var listDayView: ArrayList = arrayListOf() + private var listHeaderView: ArrayList = arrayListOf() + private var heightOfHeader: Int = 50 + private var isShowingHeader: Boolean = true + // data + private var listOfBean: Array = arrayOf() + // state, flag + private var isInitializing: Boolean = false + + + // Constraint Layout ----------------------------------------------------- + override fun onAttachedToWindow() { + super.onAttachedToWindow() + // Create day views and add. + createdDayView() + // Bind day views with data + setData(LocalDate.now()) + if (listDayView.isNotEmpty()) { + for (i in 0 until numberOfRow) { + bindWidthData(listDayView[i], listOfBean[i]) + } + } + // Create view for day of week + createHeader() + } + + // size + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + isInitializing = true + val selfW = MeasureSpec.getSize(widthMeasureSpec) + val selfH = MeasureSpec.getSize(heightMeasureSpec) + // Set size of day views + listDayView.forEachIndexed { _, view -> + Log.e(tag, "idLayout ${idLayout}") + view.layoutParams = LayoutParams(selfW/numberOfRow, selfH) + } + // Set size of view for day of week + Log.e(tag, "listHeaderView.size ${listHeaderView.size}") + listHeaderView.forEachIndexed { _, view -> + view.layoutParams = LayoutParams(selfW/numberOfRow, if (isShowingHeader) heightOfHeader else 0) + } + isInitializing = false + } + + // location + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + // Locate view for day of week + locatedHeaderView(listHeaderView) + // Locate day views + locatedDayView(listDayView) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + } + + override fun requestLayout() { + if (isInitializing) { + return + } + super.requestLayout() + Log.e(tag, "on requestLayout") + } + // ------------------------------------------------------------------------- + + // BaseCustomLayout ------------------------------------------ +// override fun initLayout(context: Context?) { +// super.initLayout(context) +// } + // ----------------------------------------------------------- + + + private fun createdDayView() { + Log.e(tag, "on createdDayView") + isInitializing = true + // create and add to listDayView + listDayView.clear() + for (i in 0 until numberOfRow) { + Log.e(tag, "idLayout ${idLayout}") + listDayView.add(LayoutInflater.from(context).inflate(idLayout, this, false)) + } + Log.e(tag, "listDayView.size ${listDayView.size}") + // add children + listDayView.forEach { + this.addView(it) + } + isInitializing = false + } + + private fun locatedDayView(list: ArrayList) { + var mutableX = this.x.toInt() + val mutableY = this.y.toInt() + val headerH = if (isShowingHeader) heightOfHeader else 0 + isInitializing = true + list.forEach { + if (this.contains(it) && + it.visibility != GONE) { + it.layout(mutableX, mutableY + headerH, mutableX + it.measuredWidth, mutableY + it.measuredHeight + headerH) + mutableX += it.measuredWidth + Log.e(tag, "locatedDayView x y ${mutableX}, ${ this.y}") + } + } + isInitializing = false + requestLayout() + } + + private fun setData(date: LocalDate) { + listOfBean = arrayOf() + listOfBean = CalendarFactory().getBeansOfWeek(date) + } + + private fun bindWidthData(view: View, bean: CalendarBean) { + textViewNumOfDay = view.findViewById(idTextViewNumOfDay).apply { + this.text = bean.getNumOfDay().toString() + } + } + + fun createHeader() { + //todo 주간 요일 표시 + for (i in 0 until numberOfRow) { + Log.e(tag, "getDayOfWeek ${listOfBean[i].getDayOfWeek()}") + TextView(context).apply { + this.text = listOfBean[i].getDayOfWeek() + this.textSize = 8f + this.width = listDayView[i].width + this.height = 50 + this.gravity = Gravity.CENTER + this.setBackgroundColor(Color.parseColor("#eeeeee")) + listHeaderView.add(this) + this@WeekLayout.addView(this) + } + } + } + + fun locatedHeaderView(list: ArrayList) { + var mutableX = this.x.toInt() + val mutableY = this.y.toInt() + val headerH = if (isShowingHeader) heightOfHeader else 0 + isInitializing = true + list.forEach { + if (this.contains(it) && + it.visibility != GONE) { + it.layout(mutableX, mutableY, mutableX + it.measuredWidth, mutableY + headerH) + mutableX += it.measuredWidth + Log.e(tag, "locatedHeaderView x y ${mutableX}, ${ this.y}") + } + } + isInitializing = false + requestLayout() + } +} + diff --git a/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarFactory.kt b/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarFactory.kt index fdf1a7f..040c3d9 100644 --- a/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarFactory.kt +++ b/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarFactory.kt @@ -1,6 +1,7 @@ package com.example.calrendarview.model import android.os.Build +import android.util.Log import androidx.annotation.RequiresApi import java.time.DayOfWeek import java.time.LocalDate @@ -19,9 +20,53 @@ class CalendarFactory { fun getBeansOfThisWeek(): Array = getBeansOfWeek(LocalDate.now()) fun getBeansOfMonth(y: Int, m:Int): Array { + Log.d("CalendarFactory", "YearMonth.of(y, m) : ${YearMonth.of(y, m)}") + Log.d("CalendarFactory", "YearMonth.of(y, m).lengthOfMonth() : ${YearMonth.of(y, m).lengthOfMonth()}") val daysInMonth = YearMonth.of(y, m).lengthOfMonth() - return Array(daysInMonth) { + val thisMonth = Array(daysInMonth) { CalendarBean(y, m, it + 1) } + + val lastY = if (m != 1) y else y - 1 + val lastM = if (m != 1) m - 1 else 12 + val lastDaysInMonth = YearMonth.of(lastY, lastM).lengthOfMonth() + val lastMonth = Array(lastDaysInMonth) { + CalendarBean(lastY, lastM, it + 1) + } + var lastArray : Array = arrayListOf().run { + if (thisMonth[0].getDayOfWeek() != "SUNDAY") { + for (i in lastMonth.size - 1 downTo 0) { + this.add(lastMonth[i]) + if (lastMonth[i].getDayOfWeek() == "SUNDAY") { + break + } + } + } + arrayOf() + this + } + + + val nextY = if (m != 12) y else y + 1 + val nextM = if (m != 12) m + 1 else 1 + val nextDaysInMonth = YearMonth.of(nextY, nextM).lengthOfMonth() + val nextMonth = Array(nextDaysInMonth) { + CalendarBean(nextY, nextM, it + 1) + } + var nextArray : ArrayList = arrayListOf() + val need = 42 - (thisMonth + lastArray).size + for (i in 0 until need) { + nextArray.add(nextMonth[i]) + } + + val r = lastArray.reversedArray() + thisMonth + nextArray + return r + } + fun getBeansOfMonth(pod: CalendarPod): Array = getBeansOfMonth(pod.year, pod.month) + + + fun getBeansOfThisMonth(): Array { + return LocalDate.now().run { + getBeansOfMonth(this.year, this.monthValue) + } } } \ No newline at end of file diff --git a/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarPod.kt b/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarPod.kt new file mode 100644 index 0000000..2dd3455 --- /dev/null +++ b/CalrendarView/src/main/java/com/example/calrendarview/model/CalendarPod.kt @@ -0,0 +1,21 @@ +package com.example.calrendarview.model + +import android.os.Build +import androidx.annotation.RequiresApi +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.O) +class CalendarPod { + + constructor(date: LocalDate) { + this.year = date.year + this.month = date.monthValue + } + constructor(y: Int, m: Int) { + this.year = y + this.month = m + } + + val year: Int + val month: Int +} \ No newline at end of file diff --git a/CalrendarView/src/main/res/layout/item_day.xml b/CalrendarView/src/main/res/layout/item_day.xml index 6a61aaa..c14446d 100644 --- a/CalrendarView/src/main/res/layout/item_day.xml +++ b/CalrendarView/src/main/res/layout/item_day.xml @@ -1,5 +1,6 @@ - diff --git a/CalrendarView/src/main/res/values/attr.xml b/CalrendarView/src/main/res/values/attr.xml index 5e0da4e..a462d25 100644 --- a/CalrendarView/src/main/res/values/attr.xml +++ b/CalrendarView/src/main/res/values/attr.xml @@ -4,17 +4,18 @@ - + - + - + + \ No newline at end of file diff --git a/app/src/main/java/com/example/accountbook/calendar/CalendarLayout.kt b/app/src/main/java/com/example/accountbook/calendar/CalendarLayout.kt index 52b4b50..7f32762 100644 --- a/app/src/main/java/com/example/accountbook/calendar/CalendarLayout.kt +++ b/app/src/main/java/com/example/accountbook/calendar/CalendarLayout.kt @@ -172,7 +172,7 @@ class CalendarLayout : FrameLayout { view!!.getHitRect(rect) val isClick = rect.contains(ev.x.toInt(), ev.y.toInt()) Log.d( - TAG, + "tag", "isClickView() called with: isClick = [$isClick]" ) return isClick @@ -302,7 +302,7 @@ class CalendarLayout : FrameLayout { } companion object { - private const val TAG = "CalendarLayout" + private const val tag = "CalendarLayout" const val TYPE_OPEN = 0 diff --git a/app/src/main/java/com/example/accountbook/calendar/CalendarView.kt b/app/src/main/java/com/example/accountbook/calendar/CalendarView.kt index b513586..a3ec65d 100644 --- a/app/src/main/java/com/example/accountbook/calendar/CalendarView.kt +++ b/app/src/main/java/com/example/accountbook/calendar/CalendarView.kt @@ -158,7 +158,7 @@ class CalendarView : ViewGroup { } } Log.i( - TAG, + "tag", "onMeasure() called with: itemHeight = [$itemHeight], itemWidth = [$itemWidth]" ) lastwidthMeasureSpec = widthMeasureSpec @@ -199,6 +199,6 @@ class CalendarView : ViewGroup { } companion object { - private const val TAG = "CalendarView" + private const val tag = "CalendarView" } } \ No newline at end of file diff --git a/app/src/main/java/com/example/accountbook/calendar2/example/ActivityCalendarEx.kt b/app/src/main/java/com/example/accountbook/calendar2/example/ActivityCalendarEx.kt index 89ed62d..065068b 100644 --- a/app/src/main/java/com/example/accountbook/calendar2/example/ActivityCalendarEx.kt +++ b/app/src/main/java/com/example/accountbook/calendar2/example/ActivityCalendarEx.kt @@ -9,8 +9,8 @@ import com.example.accountbook.calendar2.CalendarLayoutListener import com.example.accountbook.calendar2.CalendarManager import com.example.accountbook.calendar2.CalendarPagerAdapter import com.example.accountbook.databinding.CalendarActivityExampleBinding -import com.example.accountbook.databinding.ExDayViewBinding -import com.example.calrendarview.DayView +//import com.example.accountbook.databinding.ExDayLayoutBinding +import com.example.calrendarview.DayLayout import com.example.calrendarview.model.CalendarBean import com.example.calrendarview.model.CalendarFactory import com.example.calrendarview.model.DayInfo @@ -26,9 +26,9 @@ class ActivityCalendarEx: AppCompatActivity() { bind = CalendarActivityExampleBinding.inflate(this.layoutInflater) // for (i in 0 until 7) { - val infos = CalendarFactory().getBeansOfThisWeek() +// val infos = CalendarFactory().getBeansOfThisWeek() // bind.otherViews.numberOfRow = 7 -// (bind.otherViews.getChildAt(i) as? DayView)?.dayInfo = infos.get(i) +// (bind.otherViews.getChildAt(i) as? DayLayout)?.infoDay = infos.get(i) // } setContentView(bind.root) } diff --git a/app/src/main/res/layout/calendar_activity_example.xml b/app/src/main/res/layout/calendar_activity_example.xml index db30e0d..1ef48b7 100644 --- a/app/src/main/res/layout/calendar_activity_example.xml +++ b/app/src/main/res/layout/calendar_activity_example.xml @@ -3,15 +3,20 @@ android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> - + + + + + + + + - + app:numOfDayId="@id/ex_text_day" /> @@ -61,7 +66,7 @@ - + diff --git a/app/src/main/res/layout/ex_day_view.xml b/app/src/main/res/layout/ex_day_view.xml index 0f8af6b..4a08557 100644 --- a/app/src/main/res/layout/ex_day_view.xml +++ b/app/src/main/res/layout/ex_day_view.xml @@ -2,40 +2,38 @@ \ No newline at end of file