Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10 create custom view movie evaluation #22

Merged
merged 39 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
53bf552
Добавляет атрибуты для кастомной вью
GoetzDeBouville Apr 30, 2024
24eea9e
Создает базовую верстку view
GoetzDeBouville Apr 30, 2024
e91f9e2
Добавляет ресурcный файл plurals.xml для плюрализации оценки
GoetzDeBouville Apr 30, 2024
5c88592
Добавляет id в верстку view
GoetzDeBouville Apr 30, 2024
610ea1b
Добавляет класс кастомной view
GoetzDeBouville Apr 30, 2024
89ac3bf
Подключает uikit к uikit_sample
GoetzDeBouville Apr 30, 2024
5a3c330
Добавляет активити MovieEvaluationExample для примера custom view
GoetzDeBouville Apr 30, 2024
db2eaef
Добавляет переход на MoviewEvaluationEcample активити
GoetzDeBouville Apr 30, 2024
5d5dc4a
Корректировки по предупреждениям detekt
GoetzDeBouville Apr 30, 2024
3416f54
Добавляет фон для селектора
GoetzDeBouville May 1, 2024
d642e1a
Добавляет верстку для MovieSelectionView
GoetzDeBouville May 1, 2024
6b9bfe4
Добавляет кастомные атрибуты для MovieSelectionView
GoetzDeBouville May 1, 2024
c7459fd
Подключает coil
GoetzDeBouville May 1, 2024
b98973e
Корректирует верстку MovieSelectionView
GoetzDeBouville May 2, 2024
1f9108a
Подключает coil к uikit
GoetzDeBouville May 2, 2024
6204ddd
Добавляет кастомный атрибут для прикреплени картинки к view
GoetzDeBouville May 2, 2024
3bdd3a1
Добавляет класс кастомной view MovieSelectionView
GoetzDeBouville May 2, 2024
9ae806c
Добавляет активити MovieSelectionExampleActivity для демонтсрации кас…
GoetzDeBouville May 2, 2024
5d84ec4
Добавляет переход на MovieSelectionExampleActivity
GoetzDeBouville May 2, 2024
2355290
Merge branch 'develop' into 10_create_custom_view_movie_evaluation
GoetzDeBouville May 2, 2024
1e1a1f5
Добавляет стили в верстку кастомной view
GoetzDeBouville May 2, 2024
c397964
Добавляет публичный метод для управления оценкой
GoetzDeBouville May 2, 2024
6a5e38d
Добавляет демо для установки значения оценки
GoetzDeBouville May 2, 2024
3ca96b0
Merge branch 'develop' into 12_create_custom_view_movie_selection
GoetzDeBouville May 2, 2024
09284d3
Подключает стиль для текста во view
GoetzDeBouville May 2, 2024
31d5019
Делает методы установки и подготовки контента публичными
GoetzDeBouville May 3, 2024
63689da
Корректирует величину радиуса скругления на view
GoetzDeBouville May 4, 2024
d43a768
12_Заменяет ImageView на ShapeableImageView для обеспечения скруглени…
GoetzDeBouville May 6, 2024
ff28d78
12_Удаляет трансформацию, т.к. скругление углов обеспечивается Shapea…
GoetzDeBouville May 6, 2024
f9d12fa
12_добавляет градиент на картинку view
GoetzDeBouville May 6, 2024
b04c726
10_фиксы по замечаниям
GoetzDeBouville May 7, 2024
f148175
Merge branch 'develop' into 10_create_custom_view_movie_evaluation
GoetzDeBouville May 7, 2024
640f350
Merge branch '10_create_custom_view_movie_evaluation' into 12_create_…
GoetzDeBouville May 7, 2024
1390bf7
12_supress в коде сэмпл активити
GoetzDeBouville May 7, 2024
09ac005
Merge pull request #23 from DavayPosmotrim/12_create_custom_view_movi…
GoetzDeBouville May 8, 2024
e612336
10_исправляет ошибку при сборке проекта (комментирует не используемые…
GoetzDeBouville May 8, 2024
f626c88
Merge remote-tracking branch 'origin/10_create_custom_view_movie_eval…
GoetzDeBouville May 8, 2024
9f13d5b
10_исправляет ошибку при сборке проекта (комментирует не используемые…
GoetzDeBouville May 8, 2024
66f5521
Удаляет не используемые импорты
GoetzDeBouville May 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions app/src/main/java/com/davay/android/app/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package com.davay.android.app
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.fragment.NavHostFragment
import com.davay.android.R
import com.davay.android.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
Expand All @@ -13,8 +11,8 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(binding.root)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container_view) as NavHostFragment
val navController = navHostFragment.navController
// val navHostFragment =
// supportFragmentManager.findFragmentById(R.id.fragment_container_view) as NavHostFragment
// val navController = navHostFragment.navController
}
}
116 changes: 116 additions & 0 deletions uikit/src/main/java/com/davai/uikit/MovieEvaluationVIew.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.davai.uikit

import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.StyleRes
import androidx.core.content.ContextCompat
import java.util.Locale

class MovieEvaluationVIew @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
@StyleRes defStyleRes: Int = 0
) : LinearLayout(
context,
attrs,
defStyleAttr,
defStyleRes
) {
private var tvRateNumber: TextView? = null
private var tvNumberRates: TextView? = null
private var tvRateService: TextView? = null
private var body: LinearLayout? = null

init {
initViews()
applyAttributes(
context,
attrs,
defStyleAttr,
defStyleRes
)
}

private fun initViews() {
LayoutInflater.from(context).inflate(
R.layout.movie_evaluation_view,
this,
true
)
tvRateNumber = findViewById(R.id.tv_rate_number)
tvNumberRates = findViewById(R.id.tv_number_rates)
tvRateService = findViewById(R.id.tv_rate_service)
body = findViewById(R.id.ll_evaluation_body)
}

private fun applyAttributes(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) {
context.theme.obtainStyledAttributes(
attrs,
R.styleable.MovieEvaluationView,
defStyleAttr,
defStyleRes
).apply {
try {
val rateNum = getFloat(R.styleable.MovieEvaluationView_rate_num, 0.0f)
val numberOfRates = getInt(R.styleable.MovieEvaluationView_number_of_rates, 0)
val rateService = getString(R.styleable.MovieEvaluationView_rate_service).toString()

setNumberOfRatesString(numberOfRates)
setRateNum(rateNum)
setServiceNameString(rateService)
} finally {
recycle()
}
}
}

fun setRateNum(rateNum: Float) {
tvRateNumber?.text = rateNum.toString()
setItemBackground(rateNum)
}

private fun setItemBackground(rate: Float) {
val color = ContextCompat.getColor(
context,
when {
rate < BAD_RATE -> R.color.error
rate >= GOOD_RATE -> R.color.done
else -> R.color.attention
}
)
body?.backgroundTintList = ColorStateList.valueOf(color)
}

/**
* Метод setNumberOfRatesString принимает количество оценок и возвращает строку с разделением
* числа по разрядам и плюралом слова "оценка"
*/
fun setNumberOfRatesString(numberOfRates: Int) {
val formattedNumber = String.format(Locale.ROOT, "%,d", numberOfRates).replace(",", " ")
tvNumberRates?.text =
resources.getQuantityString(R.plurals.rate_nums, numberOfRates, formattedNumber)
}

/**
* Метод setServiceNameString принимает строку с названием сервиса в виде "Рейтинг IMDb"
*/
fun setServiceNameString(rateService: String) {
tvRateService?.text = rateService
}

private companion object {
const val BAD_RATE = 5
const val GOOD_RATE = 7
}
}
100 changes: 100 additions & 0 deletions uikit/src/main/java/com/davai/uikit/MovieSelectionView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.davai.uikit

import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.AttrRes
import androidx.annotation.StyleRes
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import coil.load

class MovieSelectionView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
@AttrRes defStyleAttr: Int = 0,
@StyleRes defStyleRes: Int = 0
) : ConstraintLayout(
context,
attrs,
defStyleAttr,
defStyleRes
) {
private var tvTitle: TextView? = null
private var ivSelectorIcon: ImageView? = null
private var ivThemeCover: ImageView? = null
private var body: ConstraintLayout? = null
private var isSelected = false
private var backgroundColor = -1

init {
initViews()
applyAttributes(context, attrs, defStyleAttr, defStyleRes)
}

private fun initViews() {
LayoutInflater.from(context).inflate(R.layout.movie_selection_view, this)
tvTitle = findViewById(R.id.tv_theme_title)
ivSelectorIcon = findViewById(R.id.iv_selector_icon)
ivThemeCover = findViewById(R.id.iv_theme_cover)
body = findViewById(R.id.cl_evaluation_body)
body?.background?.callback = this
}

private fun applyAttributes(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) {
context.theme.obtainStyledAttributes(
attrs,
R.styleable.MovieSelectionView,
defStyleAttr,
defStyleRes
).apply {
tvTitle?.text = getString(R.styleable.MovieSelectionView_theme_title)
isSelected = getBoolean(R.styleable.MovieSelectionView_is_selected, false)
setBackgroundColor()
setBodyTint()
setSelectorIconVisibility()
}
}

fun setThemeCover(url: String) {
ivThemeCover?.load(url) {
error(R.drawable.error_img)
placeholder(R.drawable.placeholder_img)
}
}

fun switchSelection(): Boolean {
isSelected = !isSelected
setBackgroundColor()
setBodyTint()
setSelectorIconVisibility()
return isSelected
}

private fun setBackgroundColor() {
backgroundColor = ContextCompat.getColor(
context, if (isSelected) R.color.secondary_base else R.color.background_white
)
}

private fun setBodyTint() {
body?.backgroundTintList = ColorStateList.valueOf(backgroundColor)
}

private fun setSelectorIconVisibility() {
ivSelectorIcon?.isVisible = isSelected
}

fun setThemeTitle(title: String) {
tvTitle?.text = title
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="@android:color/transparent"
android:endColor="@android:color/black"
android:angle="270" />
<corners
android:bottomLeftRadius="@dimen/card_radius_16"
android:bottomRightRadius="@dimen/card_radius_16" />
</shape>
26 changes: 13 additions & 13 deletions uikit/src/main/res/drawable/error_img.xml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="120dp" android:viewportHeight="512" android:viewportWidth="512" android:width="120dp">

<path android:fillColor="#8B7E7F" android:pathData="M182.23,399.45l0,103.47l101.3,0l0,-103.5z"/>

<path android:fillColor="#00000000" android:pathData="M424.88,370.06L41.29,370.06" android:strokeColor="#000000" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="15"/>

<path android:fillColor="#463836" android:pathData="M457.5,126.38c0,-12.11 -9.91,-22.02 -22.02,-22.02H30.28c-12.11,0 -22.02,9.91 -22.02,22.02v244.44l224.62,22.02l224.62,-22.02V126.38z"/>

<path android:fillColor="#C2B8B9" android:pathData="M8.26,370.82v28.63c0,12.11 9.91,22.02 22.02,22.02h405.2c12.11,0 22.02,-9.91 22.02,-22.02v-28.63H8.26z"/>

<path android:fillColor="#FFD24D" android:pathData="M503.74,108.92c0,-56.05 -57.21,-101.48 -127.78,-101.48c-70.57,0 -127.78,45.44 -127.78,101.48c0,50.07 45.66,91.67 105.72,99.97h-0.18c3.15,19.36 -2.66,39.92 -17.45,54.85c31.74,0 57.93,-23.9 61.91,-54.84h-0.18C458.06,200.6 503.74,158.99 503.74,108.92z"/>

<path android:fillColor="#FF000000" android:pathData="M355.83,495.48h-63.39v-40.47c0,-4.56 -3.7,-8.26 -8.26,-8.26s-8.26,3.7 -8.26,8.26v40.47h-85.68v-40.47c0,-4.56 -3.7,-8.26 -8.26,-8.26s-8.26,3.7 -8.26,8.26v40.47h-63.39c-4.56,0 -8.26,3.7 -8.26,8.26c0,4.56 3.7,8.26 8.26,8.26h245.49c4.56,0 8.26,-3.7 8.26,-8.26C364.09,499.18 360.39,495.48 355.83,495.48z"/>

<path android:fillColor="#FF000000" android:pathData="M457.91,212.37c-4.56,0 -8.26,3.7 -8.26,8.26v178.83c0,7.86 -6.4,14.26 -14.26,14.26H30.78c-7.86,0 -14.26,-6.4 -14.26,-14.26v-271.76c0,-7.86 6.4,-14.26 14.26,-14.26h184.37c4.56,0 8.26,-3.7 8.26,-8.26s-3.7,-8.26 -8.26,-8.26H30.78C13.81,96.93 0,110.73 0,127.71v271.76c0,16.97 13.81,30.78 30.78,30.78h404.61c16.97,0 30.78,-13.81 30.78,-30.78V220.63C466.17,216.07 462.48,212.37 457.91,212.37z"/>

<path android:fillColor="#FF000000" android:pathData="M375.96,0c-75.01,0 -136.04,49.23 -136.04,109.74c0,51.82 44.31,96.03 106.28,107.11c0.86,15.5 -4.84,30.83 -15.8,41.9c-2.35,2.37 -3.04,5.91 -1.75,8.99c1.28,3.08 4.29,5.08 7.62,5.08c33.33,0 61.98,-23.62 69.04,-55.89C467.5,205.97 512,161.68 512,109.74C512,49.23 450.97,0 375.96,0zM396.86,201.54c-4.3,0.59 -7.4,4.41 -7.11,8.73c-3.16,19.95 -16.95,36.08 -35,42.73c6.72,-13.01 9.41,-27.97 7.39,-42.79c0.26,-4.3 -2.83,-8.09 -7.11,-8.68c-57.13,-7.9 -98.6,-46.5 -98.6,-91.79c0,-51.41 53.62,-93.23 119.53,-93.23s119.52,41.82 119.52,93.22C495.48,155.04 454.01,193.65 396.86,201.54z"/>

<path android:fillColor="#FF000000" android:pathData="M330.92,100.92c-4.86,0 -8.82,3.96 -8.82,8.82s3.96,8.82 8.82,8.82c4.86,0 8.82,-3.96 8.82,-8.82S335.78,100.92 330.92,100.92z"/>

<path android:fillColor="#FF000000" android:pathData="M421,100.92c-4.86,0 -8.82,3.96 -8.82,8.82s3.96,8.82 8.82,8.82s8.82,-3.96 8.82,-8.82S425.87,100.92 421,100.92z"/>

<path android:fillColor="#FF000000" android:pathData="M375.96,100.92c-4.86,0 -8.82,3.96 -8.82,8.82s3.96,8.82 8.82,8.82c4.86,0 8.82,-3.96 8.82,-8.82S380.82,100.92 375.96,100.92z"/>

<path android:fillColor="#FF000000" android:pathData="M33.03,370.89c0,4.56 3.7,8.26 8.26,8.26h383.59c4.56,0 8.26,-3.7 8.26,-8.26c0,-4.56 -3.7,-8.26 -8.26,-8.26H41.29C36.73,362.63 33.03,366.33 33.03,370.89z"/>

</vector>
6 changes: 6 additions & 0 deletions uikit/src/main/res/drawable/evaluation_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/icon_tertiary" />
<corners android:radius="@dimen/card_radius_12" />
</shape>
10 changes: 10 additions & 0 deletions uikit/src/main/res/drawable/ic_selected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,16C12.418,16 16,12.418 16,8C16,3.582 12.418,0 8,0C3.582,0 -0,3.582 -0,8C-0,12.418 3.582,16 8,16ZM11.824,6.224C12.059,5.99 12.059,5.61 11.824,5.376C11.59,5.141 11.21,5.141 10.976,5.376L7,9.352L5.024,7.376C4.79,7.141 4.41,7.141 4.176,7.376C3.941,7.61 3.941,7.99 4.176,8.224L6.576,10.624C6.81,10.859 7.19,10.859 7.424,10.624L11.824,6.224Z"
android:fillColor="@color/secondary_base"
android:fillType="evenOdd"/>
</vector>
6 changes: 6 additions & 0 deletions uikit/src/main/res/drawable/selection_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/background_white" />
<corners android:radius="@dimen/card_radius_24" />
</shape>
41 changes: 41 additions & 0 deletions uikit/src/main/res/layout/movie_evaluation_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_evaluation_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/evaluation_background"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/padding_12"
android:paddingVertical="@dimen/padding_16">

<TextView
android:id="@+id/tv_rate_number"
style="@style/Text.Headline.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="@dimen/padding_16"
tools:text="[7.1]" />

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/tv_rate_service"
style="@style/Text.Base.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="[Рейтинг IMDb]" />

<TextView
android:id="@+id/tv_number_rates"
style="@style/Text.Base.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="[1 244 оценки]" />
</LinearLayout>

</LinearLayout>
Loading
Loading