Сделано

This commit is contained in:
Marat Zargarov 2023-11-21 12:06:54 +04:00
parent 6d16372dd4
commit 7aa7a2ffd9
15 changed files with 633 additions and 17 deletions

1
.idea/vcs.xml generated
View File

@ -2,5 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/assets/texts" vcs="Git" />
</component>
</project>

View File

@ -5,7 +5,7 @@ plugins {
android {
namespace = "com.example.shortbooks"
compileSdk = 33
compileSdk = 34
defaultConfig {
applicationId = "com.example.shortbooks"
@ -53,8 +53,9 @@ dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation("androidx.activity:activity-compose:1.8.1")
implementation("androidx.activity:activity-compose:1.8.0")
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
implementation("androidx.navigation:navigation-compose:2.6.0")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,15 +1,16 @@
package com.example.shortbooks
import android.content.res.Configuration
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.shortbooks.navigation.MainNavbar
import com.example.shortbooks.ui.theme.ShortBooksTheme
class MainActivity : ComponentActivity() {
@ -17,30 +18,26 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
ShortBooksTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
MainNavbar()
}
}
}
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
fun MainNavbarPreview() {
ShortBooksTheme {
Greeting("Android")
Surface(
color = MaterialTheme.colorScheme.background
) {
MainNavbar()
}
}
}

View File

@ -0,0 +1,109 @@
package com.example.shortbooks.book.composeui
import android.content.res.AssetManager
import android.content.res.Configuration
import android.graphics.BitmapFactory
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.shortbooks.book.model.getBooks
import com.example.shortbooks.navigation.Screen
import com.example.shortbooks.ui.theme.ShortBooksTheme
@Composable
fun BookList(navController: NavController?) {
Column(
Modifier
.padding(all = 10.dp)
.padding(vertical = 30.dp)
.verticalScroll(rememberScrollState()))
{
Text(text = "Книги", fontSize = 32.sp, modifier = Modifier.padding(all=10.dp))
getBooks().forEachIndexed() { index, book ->
val bookId = Screen.BookText.route.replace("{id}", index.toString())
Card(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp)
.clickable { navController?.navigate(bookId) },
shape = RoundedCornerShape(10.dp),
) {
Box(){
Row(
verticalAlignment = Alignment.CenterVertically
){
ImageConverse(imagePath = book.image)
Column {
Text("${book.name}", fontSize = 22.sp)
Text("${book.author}", fontSize = 18.sp)
}
}
}
}
}
}
}
@Composable
fun ImageConverse(imagePath: String) {
val context = LocalContext.current
val assetManager: AssetManager = context.assets
// Открываем поток данных для изображения в каталоге assets
val inputStream = assetManager.open(imagePath)
// Преобразуем поток данных в Bitmap
val bitmap = BitmapFactory.decodeStream(inputStream)
// Преобразуем Bitmap в ImageBitmap
val imageBitmap = bitmap.asImageBitmap()
// Создаем BitmapPainter из ImageBitmap
val painter = BitmapPainter(imageBitmap)
// Отображаем изображение с помощью Image и BitmapPainter
Image(
painter = painter,
contentDescription = "Image",
modifier = Modifier
.padding(all = 5.dp)
.size(64.dp)
.clip(RoundedCornerShape(10.dp))
)
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun BookListPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
BookList(navController = null)
}
}
}

View File

@ -0,0 +1,54 @@
package com.example.shortbooks.book.composeui
import android.content.res.AssetManager
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import com.example.shortbooks.book.model.getBooks
import com.example.shortbooks.ui.theme.ShortBooksTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BookText(id: Int) {
val context = LocalContext.current
val assetManager: AssetManager = context.assets
val book = getBooks()[id]
val textContent: String = assetManager.open(book.text).bufferedReader().use { it.readText() }
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = { }) {
Text(text = "Добавить в избранное")
}
Text(text = textContent, modifier = Modifier.verticalScroll(rememberScrollState()))
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun BookTextPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
BookText(id = 0)
}
}
}

View File

@ -0,0 +1,18 @@
package com.example.shortbooks.book.model
import java.io.Serializable
data class Book(
val name: String,
val author: String,
val ageLimit: Int,
val text: String,
val image: String
):Serializable
fun getBooks(): List<Book> {
return listOf(
Book("Книга 1", "Автор 1", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"),
Book("Книга 2", "Автор 2", 12, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"),
Book("Книга 3", "Автор 3", 6, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"),
)
}

View File

@ -0,0 +1,107 @@
package com.example.shortbooks.favorite.composeui
import android.content.res.AssetManager
import android.content.res.Configuration
import android.graphics.BitmapFactory
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.shortbooks.favorite.model.getFavorites
import com.example.shortbooks.navigation.Screen
import com.example.shortbooks.ui.theme.ShortBooksTheme
@Composable
fun FavoriteList(navController: NavController?) {
Column(
Modifier
.padding(all = 10.dp)
.padding(vertical = 30.dp)
.verticalScroll(rememberScrollState())) {
Text(text = "Избранное", fontSize = 32.sp, modifier = Modifier.padding(all=10.dp))
getFavorites().forEachIndexed() { index, favorite ->
val favoriteId = Screen.FavoriteText.route.replace("{id}", index.toString())
Card(
modifier = Modifier
.fillMaxWidth()
.padding(all = 10.dp)
.clickable { navController?.navigate(favoriteId) },
shape = RoundedCornerShape(15.dp),
)
{
Box(){
Row(
verticalAlignment = Alignment.CenterVertically
){
ImageConverse(imagePath = favorite.image)
Column {
Text("${favorite.name}", fontSize = 22.sp)
Text("${favorite.author}", fontSize = 18.sp)
}
}
}
}
}
}
}
@Composable
fun ImageConverse(imagePath: String, modifier: Modifier = Modifier) {
val context = LocalContext.current
val assetManager: AssetManager = context.assets
// Открываем поток данных для изображения в каталоге assets
val inputStream = assetManager.open(imagePath)
// Преобразуем поток данных в Bitmap
val bitmap = BitmapFactory.decodeStream(inputStream)
// Преобразуем Bitmap в ImageBitmap
val imageBitmap = bitmap.asImageBitmap()
// Создаем BitmapPainter из ImageBitmap
val painter = BitmapPainter(imageBitmap)
// Отображаем изображение с помощью Image и BitmapPainter
Image(
painter = painter,
contentDescription = "Image",
modifier = modifier
.padding(all = 5.dp)
.size(64.dp)
.clip(RoundedCornerShape(10.dp))
)
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun BookListPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
FavoriteList(navController = null)
}
}
}

View File

@ -0,0 +1,54 @@
package com.example.shortbooks.favorite.composeui
import android.content.res.AssetManager
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import com.example.shortbooks.favorite.model.getFavorites
import com.example.shortbooks.ui.theme.ShortBooksTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FavoriteText(id: Int) {
val context = LocalContext.current
val assetManager: AssetManager = context.assets
val favorite = getFavorites()[id]
val textContent: String = assetManager.open(favorite.text).bufferedReader().use { it.readText() }
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = { }) {
Text(text = "Удалить из избранного")
}
Text(text = textContent, modifier = Modifier.verticalScroll(rememberScrollState()))
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun BookTextPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
FavoriteText(id = 0)
}
}
}

View File

@ -0,0 +1,17 @@
package com.example.shortbooks.favorite.model
import java.io.Serializable
data class Favorite(
val name: String,
val author: String,
val ageLimit: Int,
val text: String,
val image: String
):Serializable
fun getFavorites(): List<Favorite>{
return listOf(
Favorite( "Книга 1", "Автор 1", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"),
Favorite( "Книга 2", "Автор 2", 18, "texts/dostoevskiy_besy.txt", "images/dostoevskiy_besy.jpg"),
)
}

View File

@ -0,0 +1,121 @@
package com.example.shortbooks.navigation
import android.content.res.Configuration
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.example.shortbooks.book.composeui.BookList
import com.example.shortbooks.book.composeui.BookText
import com.example.shortbooks.favorite.composeui.FavoriteList
import com.example.shortbooks.favorite.composeui.FavoriteText
import com.example.shortbooks.ui.theme.ShortBooksTheme
import com.example.shortbooks.user.composeui.UserInfo
@Composable
fun Navbar(
navController: NavHostController,
currentDestination: NavDestination?,
modifier: Modifier = Modifier
) {
NavigationBar(modifier) {
Screen.bottomBarItems.forEach { screen ->
NavigationBarItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
@Composable
fun Navhost(
navController: NavHostController,
innerPadding: PaddingValues, modifier:
Modifier = Modifier
) {
NavHost(
navController,
startDestination = Screen.BookList.route,
modifier.padding(innerPadding)
) {
composable(Screen.BookList.route) { BookList(navController) }
composable(Screen.FavoriteList.route) { FavoriteList(navController) }
composable(Screen.UserInfo.route) { UserInfo() }
composable(
Screen.BookText.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
backStackEntry.arguments?.let { BookText(it.getInt("id")) }
}
composable(
Screen.FavoriteText.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
backStackEntry.arguments?.let { FavoriteText(it.getInt("id")) }
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainNavbar() {
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val currentScreen = currentDestination?.route?.let { Screen.getItem(it) }
Scaffold(
bottomBar = {
if (currentScreen == null || currentScreen.showInBottomBar) {
Navbar(navController, currentDestination)
}
}
) { innerPadding ->
Navhost(navController, innerPadding)
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun MainNavbarPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
MainNavbar()
}
}
}

View File

@ -0,0 +1,45 @@
package com.example.shortbooks.navigation
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.List
import androidx.compose.ui.graphics.vector.ImageVector
import com.example.shortbooks.R
enum class Screen(
val route: String,
@StringRes val resourceId: Int,
val icon: ImageVector = Icons.Filled.Favorite,
val showInBottomBar: Boolean = true
) {
BookList(
"book-list", R.string.book_main_title, Icons.Filled.List
),
FavoriteList(
"favorite-list", R.string.favorite_main_title, Icons.Filled.Favorite
),
UserInfo(
"user-info", R.string.user_main_title, Icons.Filled.AccountBox
),
BookText(
"book-view/{id}",R.string.text_main_title,showInBottomBar = false
),
FavoriteText(
"favorite-view/{id}",R.string.text_main_title,showInBottomBar = false
);
companion object {
val bottomBarItems = listOf(
BookList,
FavoriteList,
UserInfo
)
fun getItem(route: String): Screen? {
val findRoute = route.split("/").first()
return values().find { value -> value.route.startsWith(findRoute) }
}
}
}

View File

@ -0,0 +1,71 @@
package com.example.shortbooks.user.composeui
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.shortbooks.R
import com.example.shortbooks.ui.theme.ShortBooksTheme
import com.example.shortbooks.user.model.getUser
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserInfo() {
val user = getUser()
Column(
Modifier
.fillMaxWidth()
.padding(all = 20.dp,)
.padding(vertical = 30.dp)
) {
Text(text = "Профиль", fontSize=32.sp)
OutlinedTextField(modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = user.name, onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_name))
}
)
OutlinedTextField(modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = user.age.toString(), onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_age))
}
)
OutlinedTextField(modifier = Modifier
.fillMaxWidth()
.padding(vertical = 10.dp),
value = user.email, onValueChange = {}, readOnly = true,
label = {
Text(stringResource(id = R.string.user_email))
}
)
}
}
@Preview(name = "Light Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Dark Mode", showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun UserInfoPreview() {
ShortBooksTheme {
Surface(
color = MaterialTheme.colorScheme.background
) {
UserInfo()
}
}
}

View File

@ -0,0 +1,14 @@
package com.example.shortbooks.user.model
import java.io.Serializable
data class User(
val email: String,
val password: String,
val name: String,
val age: Int
): Serializable
fun getUser():User{
return User("anatoliqw@gmail.com","anatol213","Анатолий", 47)
}

View File

@ -1,3 +1,10 @@
<resources>
<string name="app_name">ShortBooks</string>
<string name="app_name">MiniBooks</string>
<string name="book_main_title">Книги</string>
<string name="text_main_title">Текст</string>
<string name="favorite_main_title">Избранное</string>
<string name="user_main_title">Профиль</string>
<string name="user_name">Имя</string>
<string name="user_email">Email</string>
<string name="user_age">Возраст</string>
</resources>