新增广告tradplus

This commit is contained in:
yuqian 2025-11-26 18:27:26 +08:00
commit 3e30a11960
136 changed files with 169469 additions and 0 deletions

15
.gitignore vendored Normal file
View 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

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

1
.idea/.name generated Normal file
View File

@ -0,0 +1 @@
Wallpaper Gallery

6
.idea/AndroidProjectSystem.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

6
.idea/compiler.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
</component>
</project>

18
.idea/deploymentTargetSelector.xml generated Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-11-26T09:42:02.052253Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=659PX8INFIUKHYXK" />
</handle>
</Target>
</DropdownSelection>
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>

21
.idea/gradle.xml generated Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$PROJECT_DIR$/../../gradle/gradle-8.11.1-bin/gradle-8.11.1" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

10
.idea/migrations.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

9
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,9 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

17
.idea/runConfigurations.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

4
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings" defaultProject="true" />
</project>

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

156
app/build.gradle.kts Normal file
View File

@ -0,0 +1,156 @@
import java.text.SimpleDateFormat
import java.util.Date
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("kotlin-kapt")
id("kotlin-parcelize")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
}
android {
val timeStamp: String = SimpleDateFormat("MM_dd_HH_mm").format(Date())
namespace = "com.design.wallpapergallery"
compileSdk = 36
defaultConfig {
applicationId = "com.design.wallpapergallery"
minSdk = 26
targetSdk = 36
versionCode = 3
versionName = "3.0"
setProperty(
"archivesBaseName",
"WallpaperGallery_V" + versionName + "(${versionCode})_$timeStamp"
)
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation("androidx.room:room-runtime:2.7.2")
kapt("androidx.room:room-compiler:2.7.2")
implementation("androidx.room:room-ktx:2.7.2")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")
implementation("androidx.activity:activity-ktx:1.10.1")
implementation("com.github.bumptech.glide:glide:4.16.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
//上传参数
implementation(files("libs/UpLoadLibrary_11_24_18_30-release.aar"))
implementation(files("libs/TradPlusLibrary_11_25_15_02-release.aar"))
// implementation ("com.squareup.okhttp3:okhttp:4.12.0") 已经有了
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
implementation ("com.google.android.gms:play-services-ads-identifier:18.0.1")
// TradPlus
implementation("com.tradplusad:tradplus:14.5.0.1")
//noinspection GradleCompatible
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("androidx.appcompat:appcompat:1.3.0-alpha02")
// Meta
implementation("com.facebook.android:audience-network-sdk:6.20.0")
implementation("com.tradplusad:tradplus-facebook:1.14.5.0.1")
// Applovin
implementation("com.applovin:applovin-sdk:13.3.1")
implementation("com.tradplusad:tradplus-applovin:9.14.5.0.1")
implementation("com.google.android.gms:play-services-ads-identifier:18.2.0")
// Ironsource
implementation("com.ironsource.sdk:mediationsdk:8.10.0")
implementation("com.tradplusad:tradplus-ironsource:10.14.5.0.1")
implementation("com.google.android.gms:play-services-appset:16.0.0")
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
implementation("com.google.android.gms:play-services-basement:17.5.0")
// Adcolony
implementation("com.adcolony:sdk:4.8.0")
implementation("com.tradplusad:tradplus-adcolony:4.14.5.0.1")
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
// Pangle
implementation("com.tradplusad:tradplus-pangle:19.14.5.0.1")
implementation("com.pangle.global:pag-sdk:7.3.0.3")
// UnityAds
implementation("com.tradplusad:tradplus-unity:5.14.5.0.1")
implementation("com.unity3d.ads:unity-ads:4.15.1")
// Chartboost
implementation("com.tradplusad:tradplus-chartboostx:15.14.5.0.1")
implementation("com.chartboost:chartboost-sdk:9.8.3")
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
implementation("com.google.android.gms:play-services-base:17.4.0")
// Inmobi
implementation("com.tradplusad:tradplus-inmobix:23.14.5.0.1")
implementation("com.inmobi.monetization:inmobi-ads-kotlin:10.8.3")
implementation("androidx.core:core-ktx:1.5.0")
implementation("com.inmobi.omsdk:inmobi-omsdk:1.5.2.0")
// Fyber
implementation("com.fyber:marketplace-sdk:8.3.7")
implementation("com.tradplusad:tradplus-fyber:24.14.5.0.1")
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
implementation("com.google.android.gms:play-services-base:17.4.0")
// Start.io
implementation("com.startapp:inapp-sdk:5.2.3")
implementation("com.tradplusad:tradplus-startapp:28.14.5.0.1")
// Mintegral
implementation("com.tradplusad:tradplus-mintegralx_overseas:18.14.5.0.1")
implementation("androidx.recyclerview:recyclerview:1.1.0")
implementation("com.mbridge.msdk.oversea:mbridge_android_sdk:16.9.71")
// Liftoff
implementation("com.tradplusad:tradplus-vunglex:7.14.5.0.1")
implementation("com.vungle:vungle-ads:7.5.0")
// Yandex
implementation("com.yandex.android:mobileads:7.13.0") {
exclude(group = "com.caverock", module = "androidsvg-aar")
}
implementation("com.tradplusad:tradplus-yandex:50.14.6.10.1")
// Bigo
implementation("com.bigossp:bigo-ads:5.4.0")
implementation("com.tradplusad:tradplus-bigo:57.14.5.0.1")
// Cross Promotion
implementation("com.tradplusad:tradplus-crosspromotion:27.14.5.0.1")
// TP Exchange
// 请注意保持与主包版本同步更新
implementation("com.google.code.gson:gson:2.8.6")
implementation("com.tradplusad:tp_exchange:40.14.5.0.1")
// Google UMP
implementation ("com.google.android.ump:user-messaging-platform:3.2.0")
// TradPlus Tools
implementation("com.tradplusad:tradplus-tool:1.1.4")
//firebase
implementation(platform("com.google.firebase:firebase-bom:33.7.0"))
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-config")
}

29
app/google-services.json Normal file
View File

@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "315513708278",
"project_id": "wallpaper-gallery-4k-hd",
"storage_bucket": "wallpaper-gallery-4k-hd.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:315513708278:android:8524866560a7df437816d7",
"android_client_info": {
"package_name": "com.design.wallpapergallery"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyA92kiE20cf9V1AX2DYz-z0gC3PeppecuU"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

Binary file not shown.

Binary file not shown.

21
app/proguard-rules.pro vendored Normal file
View 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

View File

@ -0,0 +1,37 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.design.wallpapergallery",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 3,
"versionName": "3.0",
"outputFile": "WallpaperGallery_V3.0(3)_11_26_18_12-release.apk"
}
],
"elementType": "File",
"baselineProfiles": [
{
"minApi": 28,
"maxApi": 30,
"baselineProfiles": [
"baselineProfiles/1/WallpaperGallery_V3.0(3)_11_26_18_12-release.dm"
]
},
{
"minApi": 31,
"maxApi": 2147483647,
"baselineProfiles": [
"baselineProfiles/0/WallpaperGallery_V3.0(3)_11_26_18_12-release.dm"
]
}
],
"minSdkVersionForDexing": 26
}

View File

@ -0,0 +1,24 @@
package com.design.wallpapergallery
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.design.wallpapergallery", appContext.packageName)
}
}

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<application
android:name=".IApplication"
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"
android:supportsRtl="true"
android:theme="@style/Theme.WallpaperGallery"
tools:targetApi="31">
<activity
android:name=".view.MorePhotoActivity"
android:exported="false" />
<activity
android:name=".view.StartProgressActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".view.FindByNameActivity"
android:exported="false" />
<activity
android:name=".BasicActivity"
android:exported="false" />
<activity
android:name=".view.StartDownApplyActivity"
android:theme="@style/Theme.WallpaperGallery.Main"
android:exported="false" />
<meta-data
android:name="com.startapp.sdk.MIXED_AUDIENCE"
android:value="true"/>
</application>
</manifest>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

20703
app/src/main/assets/Film.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

View File

@ -0,0 +1,120 @@
package com.design.wallpapergallery
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.databinding.ActivityBasicBinding
import com.design.wallpapergallery.view.ClassificationFragment
import com.design.wallpapergallery.view.LikeFragment
import com.design.wallpapergallery.view.FindByNameActivity
class BasicActivity : AppCompatActivity() {
private lateinit var binding: ActivityBasicBinding
private var isFragmentTransitionRunning = false
private var lastClickTime = 0L
private val CLICK_THROTTLE = 300L
private lateinit var classificationFragment: Fragment
private lateinit var likeFragment: Fragment
private lateinit var mainViewModel: MainViewModel
private var currentFragment: Fragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityBasicBinding.inflate(layoutInflater)
setContentView(binding.root)
mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
initFragments()
mainViewModel.debugDatabase()
initViews()
}
private fun updateTab(position: Int) {
binding.imgHome.isSelected = false
binding.imgLike.isSelected = false
val defaultColor = getColor(R.color.colorNotSelect)
val selectColor = getColor(R.color.colorSelect)
binding.tvStart.setTextColor(defaultColor)
binding.tvEnd.setTextColor(defaultColor)
when (position) {
0 -> {
binding.imgHome.isSelected = true
binding.tvStart.setTextColor(selectColor)
binding.view1.visibility = View.VISIBLE
binding.view2.visibility = View.INVISIBLE
}
1 -> {
binding.imgLike.isSelected = true
binding.tvEnd.setTextColor(selectColor)
binding.view1.visibility = View.INVISIBLE
binding.view2.visibility = View.VISIBLE
}
}
}
private fun initFragments() {
classificationFragment = ClassificationFragment()
likeFragment = LikeFragment()
}
private fun initViews() {
switchFragment(0)
binding.llHome.setOnClickListener {
if (System.currentTimeMillis() - lastClickTime > CLICK_THROTTLE) {
switchFragment(0)
lastClickTime = System.currentTimeMillis()
}
}
binding.llLike.setOnClickListener {
if (System.currentTimeMillis() - lastClickTime > CLICK_THROTTLE) {
switchFragment(1)
lastClickTime = System.currentTimeMillis()
}
}
binding.rlSearch.setOnClickListener {
Log.d("ClickTest", "RelativeLayout被点击了");
startActivity(Intent(this, FindByNameActivity::class.java))
}
}
private fun switchFragment(position: Int) {
if (isFragmentTransitionRunning) return
var targetFragment = when (position) {
0 -> {
if (currentFragment is ClassificationFragment) return
classificationFragment
}
1 -> {
if (currentFragment is LikeFragment) return
likeFragment
}
else -> null
}
if (targetFragment == null || binding.fragmentIn.id == View.NO_ID) return
updateTab(position)
isFragmentTransitionRunning = true
supportFragmentManager.beginTransaction().apply {
setCustomAnimations(
android.R.anim.fade_in,
android.R.anim.fade_out
)
if (targetFragment.isAdded) {
show(targetFragment)
} else {
add(binding.fragmentIn.id, targetFragment)
}
currentFragment?.takeIf { it.isAdded }?.let { hide(it) }
currentFragment = targetFragment
commit()
supportFragmentManager.executePendingTransactions()
isFragmentTransitionRunning = false
}
}
}

View File

@ -0,0 +1,83 @@
package com.design.wallpapergallery
import android.app.Application
import android.util.Log
import com.design.wallpapergallery.data.AppDataBase
import com.design.wallpapergallery.data.PhotoDao
import com.design.wallpapergallery.util.ChangeTypeUtil
import com.up.uploadlibrary.UpLoadManager
import java.io.IOException
class IApplication : Application() {
private val animaLs = "Animals.json"
private val experiment = "Experimental.json"
private val film = "Film.json"
private val nature = "Nature.json"
private val patterns = "Patterns.json"
private val street = "Street.json"
private val travel = "Travel.json"
private val wallpaper = "Featured.json"
companion object {
var classificationList: MutableList<String> = mutableListOf()
var isDataInitialized = false
private set
val TAG = "WallpaperGallery"
}
override fun onCreate() {
super.onCreate()
UpLoadManager.init(this, TAG) { _, _ ->
// 处理逻辑
null
Log.d(TAG, "upload success")
}
val database = AppDataBase.getDatabase(this)
val paperDao = database.photoDao()
Thread {
initializeData(paperDao)
isDataInitialized = true
}.start()
}
private fun initializeData(paperDao: PhotoDao) {
val names = arrayOf(animaLs, travel, experiment, film, nature, patterns, street, wallpaper)
val startTime = System.currentTimeMillis()
for (name in names) {
try {
// 在后台线程读取文件
val inputStream = assets.open(name)
val jsonData = ChangeTypeUtil.getConvert(inputStream)
Log.d("DataInit", "Loaded JSON for $name")
if (jsonData.isNotEmpty()) {
val classificationName = name.substring(0, name.indexOf("."))
// 同步添加分类名称(线程安全)
synchronized(classificationList) {
classificationList.add(classificationName)
}
// 解析数据
val photos = ChangeTypeUtil.getData(jsonData, classificationName)
// 批量插入数据
if (photos.isNotEmpty()) {
// 使用批量插入方法
paperDao.insertAll(photos)
Log.d("DataInit", "[$classificationName] insert ${photos.size} data")
}
}
} catch (e: IOException) {
Log.e("DataInit", " $name error", e)
}
}
val duration = System.currentTimeMillis() - startTime
Log.d("DataInit", "use time: ${duration}ms")
}
}

View File

@ -0,0 +1,57 @@
package com.design.wallpapergallery.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.design.wallpapergallery.R
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.listener.MainSecListener
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
import com.design.wallpapergallery.databinding.ItemAddLikeBinding
class AddLikeAdapter: RecyclerView.Adapter<AddLikeAdapter.ThreeViewHolder>() {
private lateinit var context: Context
private var list:List<Photo> = emptyList()
private lateinit var listener: MainSecListener
class ThreeViewHolder(val binding: ItemAddLikeBinding): RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ThreeViewHolder {
context=parent.context
val binding= ItemAddLikeBinding.inflate(LayoutInflater.from(context),parent,false)
return ThreeViewHolder(binding)
}
fun setList(list: List<Photo>){
this.list=list
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ThreeViewHolder, position: Int) {
val item= list[position]
val previewUrl200 = item.previewUrl200
val previewUrl400 = item.previewUrl400
holder.binding.text.text=item.description
Glide.with(context).load(previewUrl400).placeholder(R.mipmap.bg_placeholder)
.error(R.mipmap.bg_placeholder).thumbnail(
Glide.with(context)
.asDrawable()
.load(previewUrl200)
.apply(
RequestOptions()
.format(DecodeFormat.PREFER_RGB_565)
)
.placeholder(R.mipmap.bg_placeholder)
.centerCrop()
).into(holder.binding.img)
holder.binding.img.setOnClickListener {
listener.inItemClick(item)
}
}
fun setListener(listener: MainSecListener){
this.listener=listener
}
}

View File

@ -0,0 +1,63 @@
package com.design.wallpapergallery.adapter
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.ItemClassificationBinding
import com.design.wallpapergallery.listener.MainSecListener
import com.design.wallpapergallery.listener.MainFirListener
import com.design.wallpapergallery.view.StartDownApplyActivity
class ClassifyAdapter : RecyclerView.Adapter<ClassifyAdapter.ClassificationViewHolder>(),MainSecListener {
private var nameList:List<String> = mutableListOf()
private var coverAllList:List<List<Photo>> = mutableListOf()
private lateinit var context: Context
private lateinit var listener:MainFirListener
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ClassificationViewHolder {
val binding=ItemClassificationBinding.inflate(LayoutInflater.from(parent.context),parent,false)
context=parent.context
return ClassificationViewHolder(binding)
}
override fun onBindViewHolder(holder: ClassificationViewHolder, position: Int) {
holder.binding.txTitle.text = nameList[position]
val adapter=ClassifyOpenAdapter()
adapter.setCoverList(coverAllList[position])
adapter.setListener(this)
holder.binding.rvView.adapter=adapter
val linearLayoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
holder.binding.rvView.layoutManager=linearLayoutManager
holder.binding.rvView.setOnClickListener{
listener.more(nameList[position])
}
holder.binding.llView.setOnClickListener {
listener.more(nameList[position])
}
}
override fun getItemCount(): Int {
return nameList.size
}
fun setList(classificationList: MutableList<String>,list:List<List<Photo>>) {
this.nameList=classificationList
this.coverAllList=list
}
fun setListener(listener: MainFirListener){
this.listener=listener
}
class ClassificationViewHolder(val binding: ItemClassificationBinding) : RecyclerView.ViewHolder(binding.root)
override fun inItemClick(photo: Photo) {
val intent=Intent(context,StartDownApplyActivity::class.java)
intent.putExtra(StartDownApplyActivity.paperKey,photo)
context.startActivity(intent)
}
}

View File

@ -0,0 +1,70 @@
package com.design.wallpapergallery.adapter
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.design.wallpapergallery.R
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.listener.MainSecListener
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
import com.design.wallpapergallery.databinding.ItemClassifyOpenBinding
class ClassifyOpenAdapter : RecyclerView.Adapter<ClassifyOpenAdapter.MainInViewHolder>() {
private lateinit var context: Context
private var coverList: List<Photo> = mutableListOf()
private lateinit var listener: MainSecListener
class MainInViewHolder(val binding: ItemClassifyOpenBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainInViewHolder {
context = parent.context
val binding = ItemClassifyOpenBinding.inflate(LayoutInflater.from(parent.context), parent, false);
return MainInViewHolder(binding)
}
override fun getItemCount(): Int {
return coverList.size
}
override fun onBindViewHolder(holder: MainInViewHolder, position: Int) {
if(position==0){
holder.binding.start.visibility = View.VISIBLE
}else if(position==itemCount-1){
holder.binding.end.visibility = View.VISIBLE
}else{
holder.binding.start.visibility = View.GONE
holder.binding.end.visibility = View.GONE
}
val previewUrl400 = coverList[position].previewUrl400
val previewUrl200 = coverList[position].previewUrl200
Log.d("MainInAdapter", "previewUrl400 is $previewUrl400 previewUrl200 is $previewUrl200")
Glide.with(context).load(previewUrl400).placeholder(R.mipmap.bg_placeholder)
.error(R.mipmap.bg_placeholder).thumbnail(
Glide.with(context)
.asDrawable()
.load(previewUrl200)
.apply(
RequestOptions()
.format(DecodeFormat.PREFER_RGB_565)
)
.placeholder(R.mipmap.bg_placeholder)
.centerCrop()
).into(holder.binding.inImage)
holder.binding.inImage.setOnClickListener {
listener.inItemClick(coverList[position])
}
}
fun setListener(listener: MainSecListener) {
this.listener = listener
}
fun setCoverList(list: List<Photo>) {
this.coverList = list
}
}

View File

@ -0,0 +1,57 @@
package com.design.wallpapergallery.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.design.wallpapergallery.R
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.ItemMoreAndSearchBinding
import com.design.wallpapergallery.listener.MainSecListener
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
class MoreAndSearchAdapter: RecyclerView.Adapter<MoreAndSearchAdapter.DoubleViewHolder>() {
private lateinit var context:Context
private var list:List<Photo> = emptyList()
private lateinit var listener:MainSecListener
class DoubleViewHolder(val binding: ItemMoreAndSearchBinding): RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DoubleViewHolder {
context=parent.context
val binding=ItemMoreAndSearchBinding.inflate(LayoutInflater.from(context),parent,false)
return DoubleViewHolder(binding)
}
fun setList(list: List<Photo>){
this.list=list
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: DoubleViewHolder, position: Int) {
val item= list[position]
val previewUrl200 = item.previewUrl200
val previewUrl400 = item.previewUrl400
holder.binding.text.text=item.description
Glide.with(context).load(previewUrl400).placeholder(R.mipmap.bg_placeholder)
.error(R.mipmap.bg_placeholder).thumbnail(
Glide.with(context)
.asDrawable()
.load(previewUrl200)
.apply(
RequestOptions()
.format(DecodeFormat.PREFER_RGB_565)
)
.placeholder(R.mipmap.bg_placeholder)
.centerCrop()
).into(holder.binding.img)
holder.binding.img.setOnClickListener {
listener.inItemClick(item)
}
}
fun setListener(listener: MainSecListener){
this.listener=listener
}
}

View File

@ -0,0 +1,23 @@
package com.design.wallpapergallery.data
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [Photo::class], version = 1, exportSchema = false)
abstract class AppDataBase:RoomDatabase() {
abstract fun photoDao():PhotoDao
companion object{
@Volatile
private var INSTANCE:AppDataBase?=null
fun getDatabase(context:Context):AppDataBase{
return INSTANCE?: synchronized(this){
INSTANCE?:createDatabase(context).also { INSTANCE=it }
}
}
private fun createDatabase(context: Context):AppDataBase{
return Room.databaseBuilder(context.applicationContext,AppDataBase::class.java,"wallpaper_database").fallbackToDestructiveMigration().build()
}
}
}

View File

@ -0,0 +1,149 @@
package com.design.wallpapergallery.data
import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.design.wallpapergallery.IApplication
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val repository: PhotoRepository by lazy {
val dao = AppDataBase.getDatabase(application).photoDao()
PhotoRepository(dao)
}
// 防抖控制
private var lastSearchTime = 0L
private var lastQuery: String? = null
private val searchDebounceTime = 500L
// LiveData 统一暴露
private val _paperResult = MutableLiveData<Photo?>() // id查询结果
val paperResult: LiveData<Photo?> get() = _paperResult
private val _classificationList = MutableLiveData<List<Photo>>(emptyList()) // 类别列表
val classificationList: LiveData<List<Photo>> get() = _classificationList
private val _coverMap = MutableLiveData<Map<String, List<Photo>>>(emptyMap()) // 封面分类映射
val coverMap: LiveData<Map<String, List<Photo>>> get() = _coverMap
private val _loadingState = MutableLiveData(false) // 加载状态
val loadingState: LiveData<Boolean> get() = _loadingState
private val _searchList = MutableLiveData<List<Photo>>(emptyList()) // 搜索结果
val searchList: LiveData<List<Photo>> get() = _searchList
private val _isLiked = MutableLiveData<Boolean?>() // 是否收藏
val isLiked: LiveData<Boolean?> get() = _isLiked
val likePhotos: LiveData<List<Photo>> get() = repository.getLikes()
// 添加标题存储
var currentTitleName: String? = null
fun debugDatabase() {
viewModelScope.launch(Dispatchers.IO) {
try {
val photos = repository.allPhoto()
Log.d("DB_DEBUG", "总记录数: ${photos.size}")
photos.take(5).forEach { paper ->
Log.d("DB_DEBUG", "Photo[${paper.id}]: " +
"cat=${paper.classificationName}, " +
"imId=${paper.imId}, " +
"desc=${paper.description.take(10)}...")
}
} catch (e: Exception) {
Log.e("DB_DEBUG", "查询失败", e)
}
}
}
fun updatePhoto(paper: Photo) {
viewModelScope.launch(Dispatchers.IO) {
repository.updatePhoto(paper)
}
}
fun getPhotoResult(id: String) {
viewModelScope.launch(Dispatchers.IO) {
_paperResult.postValue(repository.getPhotoById(id))
}
}
fun getClassificationList(name: String) {
viewModelScope.launch(Dispatchers.IO) {
_classificationList.postValue(repository.getPhotoByClassification(name))
}
}
fun loadAllClassificationCovers() {
if (_loadingState.value == true) return
viewModelScope.launch(Dispatchers.IO) {
_loadingState.postValue(true)
val classificationList = IApplication.classificationList
val resultMap = mutableMapOf<String, List<Photo>>()
val deferredList = classificationList.map { classification ->
async {
try {
classification to repository.getClassificationCover(classification)
} catch (e: Exception) {
Log.e("BatchLoad", "加载分类[$classification]失败: ${e.message}")
classification to emptyList<Photo>()
}
}
}
deferredList.awaitAll().forEach { (classification, photos) ->
resultMap[classification] = photos
}
_coverMap.postValue(resultMap)
_loadingState.postValue(false)
Log.d("BatchLoad", "所有分类封面数据加载完成")
}
}
fun getSearchList(query: String) {
val currentTime = System.currentTimeMillis()
if (query == lastQuery && (currentTime - lastSearchTime) < searchDebounceTime) {
return
}
lastQuery = query
lastSearchTime = currentTime
viewModelScope.launch(Dispatchers.IO) {
try {
_searchList.postValue(repository.searchByKey(query))
} catch (e: Exception) {
_searchList.postValue(emptyList())
Log.e("Search", "Search failed", e)
}
}
}
fun checkLike(id: String) {
viewModelScope.launch(Dispatchers.IO) {
_isLiked.postValue(repository.isLike(id))
}
}
fun setLike(paper: Photo) {
viewModelScope.launch(Dispatchers.IO) {
val updatePhoto = paper.copy(isLike = !paper.isLike)
repository.updatePhoto(updatePhoto)
Log.d("setlike status",updatePhoto.isLike.toString())
_isLiked.postValue(updatePhoto.isLike)
}
}
}

View File

@ -0,0 +1,24 @@
package com.design.wallpapergallery.data
import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
@Parcelize
@Entity(tableName = "photos",
indices = [Index(value = ["imId"], unique = true)])
data class Photo(
@PrimaryKey(autoGenerate = true) var id: Int = 0,
@ColumnInfo(name = "classificationName") var classificationName: String = "",
@ColumnInfo(name = "imId") var imId: String = "",
@ColumnInfo(name = "description") var description: String = "",
@ColumnInfo(name = "fullUrl") var fullUrl: String = "",
@ColumnInfo(name = "previewUrl1080") var previewUrl1080: String = "",
@ColumnInfo(name = "previewUrl400") var previewUrl400: String = "",
@ColumnInfo(name = "previewUrl200") var previewUrl200: String = "",
@ColumnInfo(name = "is_like") var isLike: Boolean = false,
@ColumnInfo(name = "isDownload") var isDownload: Boolean = false
):Parcelable

View File

@ -0,0 +1,39 @@
package com.design.wallpapergallery.data
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
@Dao
interface PhotoDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertAll(photos: List<Photo>)
@Update
suspend fun update(photo: Photo)
@Query("SELECT * FROM photos WHERE imId=:imId")
suspend fun getById(imId: String): Photo?
@Query("SELECT * FROM photos WHERE classificationName=:name LIMIT 4 OFFSET 20")
suspend fun queryCover(name: String): List<Photo>
@Query("SELECT * FROM photos WHERE classificationName=:name")
suspend fun queryEachGenera(name: String): List<Photo>
@Query("SELECT * FROM photos WHERE is_like = 1")
fun queryLikePhoto(): LiveData<List<Photo>>
@Query("SELECT * FROM photos WHERE description LIKE '%'||:name||'%'")
suspend fun search(name: String): List<Photo>
@Query("SELECT * FROM photos WHERE imId = :imId AND is_like = 1")
suspend fun queryIsLike(imId: String): Photo?
@Query("SELECT * FROM photos")
suspend fun getAllPhotos(): List<Photo>
}

View File

@ -0,0 +1,31 @@
package com.design.wallpapergallery.data
import androidx.lifecycle.LiveData
class PhotoRepository(private val photoDao: PhotoDao) {
suspend fun allPhoto():List<Photo>{
return photoDao.getAllPhotos()
}
// suspend fun insertPhoto(paper: Photo){
// paperDao.insert(paper)
// }
suspend fun updatePhoto(photo: Photo){
photoDao.update(photo)
}
suspend fun getPhotoById(id:String):Photo?{
return photoDao.getById(id)
}
suspend fun getClassificationCover(name:String):List<Photo>{
return photoDao.queryCover(name)
}
suspend fun getPhotoByClassification(name: String):List<Photo>{
return photoDao.queryEachGenera(name)
}
fun getLikes():LiveData<List<Photo>>{
return photoDao.queryLikePhoto()
}
suspend fun searchByKey(key:String):List<Photo>{
return photoDao.search(key)
}
suspend fun isLike(id: String): Boolean = photoDao.queryIsLike(id) != null
}

View File

@ -0,0 +1,5 @@
package com.design.wallpapergallery.listener
interface MainFirListener {
fun more(name:String)
}

View File

@ -0,0 +1,7 @@
package com.design.wallpapergallery.listener
import com.design.wallpapergallery.data.Photo
interface MainSecListener {
fun inItemClick(photo:Photo)
}

View File

@ -0,0 +1,5 @@
package com.design.wallpapergallery.listener
interface OpenTypeListener {
fun onClick(type:Int)
}

View File

@ -0,0 +1,103 @@
package com.design.wallpapergallery.util
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat
import com.design.wallpapergallery.data.Photo
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.io.Reader
import java.nio.charset.StandardCharsets
object ChangeTypeUtil {
fun getConvert(inputStream: InputStream): String {
var stringStr = ""
try {
val stringBuilder: StringBuilder = StringBuilder()
val buffer = CharArray(8192)
val reader: Reader =
BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8))
var byteRead: Int
while (reader.read(buffer).also { byteRead = it } != -1) {
stringBuilder.appendRange(buffer, 0, byteRead)
}
stringStr = stringBuilder.toString()
} catch (e: IOException) {
return stringStr
}
return stringStr
}
fun getData(data: String, name: String):List<Photo> {
val jsonArray = JSONArray(data)
val photoList = mutableListOf<Photo>()
var eachItem: JSONObject
var _description: String
var links: JSONObject
var download: String
var urls: JSONObject
var regular: String
var small: String
var thumb: String
val host = "https://unsplash.com/photos/"
var photo: Photo
var mid: String
for (i in 0 until jsonArray.length()) {
eachItem = jsonArray.getJSONObject(i)
_description = eachItem.getString("alt_description")
links = eachItem.getJSONObject("links")
download = links.getString("download")
urls = eachItem.getJSONObject("urls")
regular = urls.getString("regular")
small = urls.getString("small")
thumb = urls.getString("thumb")
mid = download.substring(host.length, download.indexOf("/download"))
photo = Photo().apply {
imId = mid
classificationName = name
description = _description
fullUrl = download
previewUrl1080 = regular
previewUrl400 = small
previewUrl200 = thumb
}
photoList.add(photo)
}
return photoList
}
fun getSaveFilePath(context: Context, imId: String): String {
return "${context.cacheDir}/${imId}.jpg"
}
fun checkPermission(context: Context,permissions:Array<String>):Boolean{
return permissions.all {
ContextCompat.checkSelfPermission(context,it)==PackageManager.PERMISSION_GRANTED
}
}
fun getStoragePermissions(): Array<String> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
arrayOf(Manifest.permission.READ_MEDIA_IMAGES)
} else {
arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
}
fun hasStoragePermission(context: Context): Boolean {
return getStoragePermissions().all { permission ->
ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
}
}
}

View File

@ -0,0 +1,132 @@
package com.design.wallpapergallery.util
import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import android.util.Log
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.util.logging.Logger
object DownPicUtils {
private val LOGGER = Logger.getLogger(DownPicUtils::class.java.name)
interface ConnectCallBack {
fun onResult(success: Boolean, inputStream: InputStream?)
}
fun downloadFile(url: String, savePath: String, callback: ConnectCallBack): Call {
val client = OkHttpClient()
val request = Request.Builder().url(url).build()
val call = client.newCall(request)
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
LOGGER.severe("Download failed: ${e.message}")
callback.onResult(false, null)
}
override fun onResponse(call: Call, response: Response) {
response.use {
try {
val responseBody = response.body
if (responseBody != null) {
val inputStream = responseBody.byteStream()
val writeSuccess = writeFile(inputStream, savePath)
callback.onResult(writeSuccess, inputStream)
} else {
LOGGER.warning("Empty response body")
callback.onResult(false, null)
}
} catch (e: Exception) {
LOGGER.severe("Error processing response: ${e.message}")
callback.onResult(false, null)
}
}
}
})
return call
}
private fun writeFile(inputStream: InputStream, filePath: String): Boolean {
val file = File(filePath)
return try {
file.parentFile?.takeIf { !it.exists() }?.mkdirs()
FileOutputStream(file).use { fos ->
val buffer = ByteArray(4096)
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
fos.write(buffer, 0, bytesRead)
}
true
}
} catch (e: Exception) {
LOGGER.severe("File write error: ${e.message}")
false
}
}
fun saveToGallery(context: Context, file: File): Uri? {
val name = "${System.currentTimeMillis()}.jpg"
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, name)
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.Images.Media.IS_PENDING, 1)
}
}
val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val contentResolver = context.contentResolver
val imgUri = contentResolver.insert(uri, contentValues) ?: run {
Log.d("MediaSaver", "Failed to create media entry")
return null
}
try {
contentResolver.openOutputStream(imgUri)?.use { outputStream ->
FileInputStream(file).use { inputStream ->
val buffer = ByteArray(4026)
var byteRead: Int
while (inputStream.read(buffer).also { byteRead = it } != -1) {
outputStream.write(buffer, 0, byteRead)
}
}
}?:run {
Log.d("MediaSaver", "Failed to open output stream")
return null
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
contentValues.clear()
contentValues.put(MediaStore.Images.Media.IS_PENDING, 0)
contentResolver.update(imgUri, contentValues, null, null)
}
return imgUri
} catch (e: IOException) {
Log.e("MediaSaver", "Error saving image to gallery", e)
// 发生错误时删除创建的文件记录
try {
contentResolver.delete(imgUri, null, null)
} catch (deleteEx: Exception) {
Log.e("MediaSaver", "Failed to delete failed media entry", deleteEx)
}
return null
}
}
}

View File

@ -0,0 +1,84 @@
package com.design.wallpapergallery.view
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.design.wallpapergallery.IApplication
import com.design.wallpapergallery.adapter.ClassifyAdapter
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.databinding.FragmentClassificationPageBinding
import com.design.wallpapergallery.listener.MainFirListener
class ClassificationFragment : Fragment(),MainFirListener {
private lateinit var binding:FragmentClassificationPageBinding
private lateinit var viewModel:MainViewModel
private lateinit var adapter: ClassifyAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding=FragmentClassificationPageBinding.inflate(inflater,container,false)
init()
return binding.root
}
private fun init(){
viewModel = ViewModelProvider(requireActivity())[MainViewModel::class.java]
adapter=ClassifyAdapter()
adapter.setListener(this)
binding.rvView.adapter = adapter
binding.rvView.layoutManager = LinearLayoutManager(requireContext())
viewModel.coverMap.value?.takeIf { it.isNotEmpty() }?.let {
Log.d("DataLoad", "hasLoad")
updateAdapter()
}
viewModel.loadAllClassificationCovers()
viewModel.loadingState.observe(viewLifecycleOwner) { isLoading ->
viewModel.coverMap.value?.let { coverMap ->
if (!isLoading && coverMap.isNotEmpty()) {
updateAdapter()
}
}
}
viewModel.coverMap.observe(viewLifecycleOwner) { coverMap ->
viewModel.loadingState.value?.let { isLoading ->
if (!isLoading && coverMap.isNotEmpty()) {
updateAdapter()
}
}
}
}
private fun updateAdapter() {
val classificationList = IApplication.classificationList
val coverMap = viewModel.coverMap.value
// 确保数据一致性
val coversForCategories = classificationList.map { classificationName ->
coverMap?.get(classificationName) ?: emptyList()
}
adapter.setList(classificationList, coversForCategories)
adapter.notifyDataSetChanged()
Log.d("AdapterUpdate", "refresh data")
classificationList.forEachIndexed { index, classification ->
val count = coversForCategories[index].size
Log.d("DataDebug", "[$index] $classification: $count data")
}
}
override fun more(name: String) {
val intent=Intent(requireActivity(),MorePhotoActivity::class.java)
intent.putExtra(MorePhotoActivity.titleName,name)
startActivity(intent)
}
}

View File

@ -0,0 +1,57 @@
package com.design.wallpapergallery.view
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.design.wallpapergallery.adapter.AddLikeAdapter
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.FragmentLikePageBinding
import com.design.wallpapergallery.listener.MainSecListener
class LikeFragment : Fragment(),MainSecListener {
private lateinit var binding: FragmentLikePageBinding
private lateinit var viewModel: MainViewModel
private lateinit var adapter:AddLikeAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding=FragmentLikePageBinding.inflate(inflater,container,false)
init()
return binding.root
}
private fun init(){
viewModel=ViewModelProvider(requireActivity())[MainViewModel::class.java]
adapter=AddLikeAdapter()
adapter.setListener(this)
viewModel.likePhotos.observe(viewLifecycleOwner) { photos ->
Log.d("LikeFragment","paper is$photos")
if (photos.isNullOrEmpty()) {
// 可以在这里显示空状态视图
binding.layoutNoData.visibility = View.VISIBLE
binding.rvView.visibility = View.GONE
} else {
binding.layoutNoData.visibility = View.GONE
binding.rvView.visibility = View.VISIBLE
adapter.setList(photos)
adapter.notifyDataSetChanged()
}
}
val gridLayoutManager = GridLayoutManager(requireActivity(), 3)
binding.rvView.layoutManager=gridLayoutManager
binding.rvView.adapter=adapter
}
override fun inItemClick(paper: Photo) {
val intent= Intent(context, StartDownApplyActivity::class.java)
intent.putExtra(StartDownApplyActivity.paperKey,paper)
startActivity(intent)
}
}

View File

@ -0,0 +1,128 @@
package com.design.wallpapergallery.view
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.ad.tradpluslibrary.TPAdManager.showTPAD
import com.design.wallpapergallery.R
import com.design.wallpapergallery.adapter.MoreAndSearchAdapter
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.ActivityFindByNameBinding
import com.design.wallpapergallery.listener.MainSecListener
class FindByNameActivity : AppCompatActivity(), MainSecListener {
lateinit var binding: ActivityFindByNameBinding
private lateinit var viewModel: MainViewModel
private lateinit var adapter: MoreAndSearchAdapter
private var resultList: List<Photo> = emptyList()
private var searchKey = ""
private var isClick = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFindByNameBinding.inflate(layoutInflater)
setContentView(binding.root)
init()
}
private fun init() {
showTPAD(this) { null }
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
adapter = MoreAndSearchAdapter()
adapter.setListener(this)
binding.list.adapter = adapter
binding.list.layoutManager = GridLayoutManager(this, 2)
binding.tvStart.setOnClickListener { showTPAD(this) {startSearch()} }
binding.imageBack.setOnClickListener { finish() }
binding.editText.requestFocus()
binding.editText.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE) {
showTPAD(this) {
startSearch()
}
return@setOnEditorActionListener true
}
false
}
viewModel.searchList.observe(this) { list ->
resultList = list
binding.searchPb.visibility = View.GONE
Log.d("SearchResult", "result list size${list.size}")
if (resultList.isNotEmpty()) {
showEmpty(false)
adapter.setList(resultList)
adapter.notifyDataSetChanged()
} else if (isClick) {
showEmpty(true)
}
}
binding.editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
searchKey = s.toString().trim()
if (searchKey.isNotEmpty()) {
binding.tvStart.visibility = View.VISIBLE
} else {
binding.tvStart.visibility = View.GONE
}
}
override fun afterTextChanged(s: Editable) {
}
})
}
private fun startSearch() {
closeKeyboard()
isClick = true
binding.searchPb.visibility = View.VISIBLE
if (searchKey.isNotEmpty()) {
Log.d("SearchStart", "searchKey is$searchKey")
viewModel.getSearchList(searchKey)
} else {
binding.searchPb.visibility = View.GONE
Toast.makeText(
this,
getString(R.string.please_enter),
Toast.LENGTH_SHORT
).show()
}
}
private fun showEmpty(showEmpty: Boolean) {
if (showEmpty) {
binding.emptyLayout.visibility = View.VISIBLE
binding.list.visibility = View.GONE
} else {
binding.emptyLayout.visibility = View.GONE
binding.list.visibility = View.VISIBLE
}
}
private fun closeKeyboard() {
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as? InputMethodManager
val currentFocus = currentFocus ?: binding.root
inputMethodManager?.hideSoftInputFromWindow(currentFocus.windowToken, 0)
}
override fun inItemClick(paper: Photo) {
val intent = Intent(this, StartDownApplyActivity::class.java)
intent.putExtra(StartDownApplyActivity.paperKey, paper)
startActivity(intent)
}
}

View File

@ -0,0 +1,83 @@
package com.design.wallpapergallery.view
import android.graphics.Color
import android.view.Gravity
import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.Window
import com.design.wallpapergallery.R
import com.design.wallpapergallery.databinding.FragmentDialogSelectBinding
import com.design.wallpapergallery.listener.OpenTypeListener
import androidx.core.graphics.drawable.toDrawable
class SelectDialogFragment : androidx.fragment.app.DialogFragment() {
private lateinit var vb: FragmentDialogSelectBinding
private var listener: OpenTypeListener? = null
companion object {
const val TYPE_HOME = 0
const val TYPE_LOCK = 1
const val TYPE_BOTH = 2
}
fun setListener(listener: OpenTypeListener?) {
this.listener = listener
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: android.os.Bundle?
): android.view.View {
vb = FragmentDialogSelectBinding.inflate(layoutInflater)
init()
return vb.root
}
override fun onCreateDialog(savedInstanceState: android.os.Bundle?): android.app.Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
dialog.window?.apply {
requestFeature(Window.FEATURE_NO_TITLE)
setWindowAnimations(R.style.BottomSheetDialogStyle)
setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
setGravity(Gravity.BOTTOM)
}
return dialog
}
override fun onStart() {
super.onStart()
dialog?.apply {
setCanceledOnTouchOutside(true)
window?.apply {
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
}
}
private fun init() {
vb.layoutHome.setOnClickListener {
listener?.onClick(TYPE_HOME)
dismiss()
}
vb.layoutLock.setOnClickListener {
listener?.onClick(TYPE_LOCK)
dismiss()
}
vb.layoutBoth.setOnClickListener {
listener?.onClick(TYPE_BOTH)
dismiss()
}
}
}

View File

@ -0,0 +1,318 @@
package com.design.wallpapergallery.view
import android.app.WallpaperManager
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.ad.tradpluslibrary.TPAdManager
import com.ad.tradpluslibrary.TPAdManager.showTPAD
import com.design.wallpapergallery.R
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.ActivityPhotoDownApplyBinding
import com.design.wallpapergallery.listener.OpenTypeListener
import com.design.wallpapergallery.util.DownPicUtils
import com.design.wallpapergallery.util.ChangeTypeUtil
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.request.RequestOptions
import okhttp3.Call
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
class StartDownApplyActivity : AppCompatActivity(), OpenTypeListener {
companion object {
var paperKey = "paper"
}
private lateinit var binding: ActivityPhotoDownApplyBinding
lateinit var paper: Photo
private lateinit var viewModel: MainViewModel
private var fullUrl = ""
private var mSavePath = ""
private lateinit var wallpaperManager: WallpaperManager
private lateinit var downloadFile: File
private var call: Call? = null
private var isGranted = false
private lateinit var setDialog: SelectDialogFragment
private var isSetting = false
private val storagePermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
if (permissions.all { it.value }) {
isGranted = true
} else {
Toast.makeText(this, getString(R.string.no_permit), Toast.LENGTH_SHORT).show()
}
}
private fun requestStoragePermission() {
val permissions = ChangeTypeUtil.getStoragePermissions()
if (ChangeTypeUtil.hasStoragePermission(this)) {
isGranted = true
} else {
storagePermissionLauncher.launch(permissions)
}
}
private fun isActivityValid(): Boolean {
return !isFinishing && !isDestroyed
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPhotoDownApplyBinding.inflate(layoutInflater)
setContentView(binding.root)
init()
}
override fun onDestroy() {
super.onDestroy()
call?.let {
it.cancel()
}
deleteCacheFile()
}
private fun init() {
showTPAD(this) { null }
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
paper = intent?.getParcelableExtra(paperKey)!!
fullUrl = paper.fullUrl
mSavePath = ChangeTypeUtil.getSaveFilePath(this, paper.imId)
downloadFile = File(mSavePath)
setDialog = SelectDialogFragment()
setDialog.setListener(this@StartDownApplyActivity)
wallpaperManager = WallpaperManager.getInstance(this)
Glide.with(this)
.load(paper.previewUrl1080)
.apply(
RequestOptions()
.format(DecodeFormat.PREFER_RGB_565)
)
.skipMemoryCache(true)
.thumbnail(
Glide.with(this)
.load(paper.previewUrl400)
.apply(
RequestOptions()
.format(DecodeFormat.PREFER_RGB_565)
.centerCrop()
)
)
.into(binding.image)
binding.imageBack.setOnClickListener { showTPAD(this) { finish() } }
binding.tvContent.text = paper.description
viewModel.isLiked.observe(this) { b ->
Log.d("initb", b.toString())
if (b != null) {
binding.imageLike.isSelected = b
}
}
viewModel.checkLike(paper.imId)
binding.imageLike.setOnClickListener {
setLikeStatus()
}
binding.layoutDownload.setOnClickListener {
startDownload()
}
binding.layoutSet.setOnClickListener {
showSetDialog()
}
}
private fun showSetDialog() {
if (isSetting) return
if (!setDialog.isAdded) {
setDialog.show(supportFragmentManager, "")
}
}
private fun setLikeStatus() {
val b = !binding.imageLike.isSelected
binding.imageLike.isSelected = !b
paper.isLike = !b
viewModel.setLike(paper)
}
private fun startDownload() {
requestStoragePermission()
if (!isGranted) return
showDownloadLoading(true)
if (downloadFile.exists()) {
saveToGallery()
return
}
doDownload()
}
private fun saveToGallery() {
val uri: Uri? = DownPicUtils.saveToGallery(this, downloadFile)
if (!isActivityValid()) return
runOnUiThread {
showDownloadLoading(false)
if (uri == null) {
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.save_fail),
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.save_success),
Toast.LENGTH_SHORT
).show()
}
Log.d("YYYYYY", "--------path=" + downloadFile.getAbsolutePath() + "---uri=" + uri)
}
}
private fun doDownload() {
call = DownPicUtils.downloadFile(fullUrl, mSavePath, object : DownPicUtils.ConnectCallBack {
override fun onResult(success: Boolean, inputStream: InputStream?) {
val file = File(mSavePath)
if (file.exists() && success) {
downloadFile = file
saveToGallery()
} else {
if (!isActivityValid()) return
runOnUiThread {
showDownloadLoading(false)
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.down_fail),
Toast.LENGTH_SHORT
).show()
}
}
}
})
}
private fun showDownloadLoading(show: Boolean) {
if (show) {
binding.pbDownload.visibility = View.VISIBLE
binding.imageDownload.visibility = View.GONE
} else {
binding.pbDownload.visibility = View.GONE
binding.imageDownload.visibility = View.VISIBLE
}
}
private fun deleteCacheFile() {
if (downloadFile.exists()) {
val delete = downloadFile.delete()
Log.d("YYYYYY", "--------delete=$delete")
}
}
override fun onClick(type: Int) {
showSetWallpaperLoading(true)
if (downloadFile.exists()) {
Thread {
Log.d("YYYYYY", "skip download and set")
setWallPaper(downloadFile, type)
}.start()
} else {
call =
DownPicUtils.downloadFile(
fullUrl,
mSavePath,
object : DownPicUtils.ConnectCallBack {
override fun onResult(success: Boolean, inputStream: InputStream?) {
val file = File(mSavePath)
if (file.exists() && success) {
downloadFile = file
setWallPaper(downloadFile, type)
} else {
showDownloadLoading(false)
runOnUiThread {
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.set_fail),
Toast.LENGTH_SHORT
).show()
}
}
}
})
}
}
private fun showSetWallpaperLoading(show: Boolean) {
Log.d("YYYYYY", "-----------showSetWallpaperLoading$show")
if (show) {
isSetting = true
binding.pbSet.visibility = View.VISIBLE
binding.txApply.visibility = View.GONE
} else {
isSetting = false
binding.pbSet.visibility = View.GONE
binding.txApply.visibility = View.VISIBLE
}
}
private fun setWallPaper(file: File, type: Int) {
try {
FileInputStream(file).use { fileInputStream ->
when (type) {
SelectDialogFragment.TYPE_HOME -> {
// FLAG_SYSTEM 表示设置为主屏幕壁纸
wallpaperManager.setStream(
fileInputStream,
null,
true,
WallpaperManager.FLAG_SYSTEM
)
}
SelectDialogFragment.TYPE_LOCK -> {
// FLAG_LOCK 设置为锁屏壁纸
wallpaperManager.setStream(
fileInputStream,
null,
true,
WallpaperManager.FLAG_LOCK
)
}
SelectDialogFragment.TYPE_BOTH -> {
// 同时设置主屏和锁屏壁纸
wallpaperManager.setStream(fileInputStream)
}
else -> {}
}
}
if (!isActivityValid()) return
runOnUiThread {
showSetWallpaperLoading(false)
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.set_success),
Toast.LENGTH_SHORT
).show()
}
} catch (e: Exception) {
if (!isActivityValid()) return
runOnUiThread {
showSetWallpaperLoading(false)
Toast.makeText(
this@StartDownApplyActivity,
getString(R.string.set_fail),
Toast.LENGTH_SHORT
).show()
}
}
}
}

View File

@ -0,0 +1,60 @@
package com.design.wallpapergallery.view
import android.content.Intent
import android.os.Bundle
import android.os.CountDownTimer
import androidx.appcompat.app.AppCompatActivity
import com.ad.tradpluslibrary.TPAdManager
import com.design.wallpapergallery.BasicActivity
import com.design.wallpapergallery.IApplication
import com.design.wallpapergallery.databinding.ActivityStartProgressBinding
class StartProgressActivity : AppCompatActivity() {
lateinit var binding: ActivityStartProgressBinding
private var countDownTimer: CountDownTimer? = null
private var time = 13000L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityStartProgressBinding.inflate(layoutInflater)
setContentView(binding.root)
TPAdManager.init(
this@StartProgressActivity,
IApplication.TAG,
"70E883D08C8D3ACA863B20E0C5CBF011",
"7B5ACED11900515030BB9A3C0D6F6812",
"D42B81ACACC02652DBD080DF0069B812",
"FA341D48027596C8C4F86B3446A7FA12"
) {
null
}
countDownTimer = TPAdManager.showWelcomeAd(
this@StartProgressActivity,
time,
{ aLong ->
val progressPercentage = (100 * aLong) / time
val percentage = 100 - progressPercentage
binding.progressbar.progress = percentage.toInt()
},
{
val intent= Intent(
this@StartProgressActivity,
BasicActivity::class.java
)
startActivity(intent)
finish()
}
)
countDownTimer?.start()
}
override fun onDestroy() {
super.onDestroy()
if (countDownTimer != null) {
countDownTimer!!.cancel()
}
}
}

View File

@ -0,0 +1,74 @@
package com.design.wallpapergallery.view
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.ad.tradpluslibrary.TPAdManager.showTPAD
import com.design.wallpapergallery.adapter.MoreAndSearchAdapter
import com.design.wallpapergallery.data.MainViewModel
import com.design.wallpapergallery.data.Photo
import com.design.wallpapergallery.databinding.ActivityTypeDescBinding
import com.design.wallpapergallery.listener.MainSecListener
class MorePhotoActivity : AppCompatActivity(),MainSecListener {
private lateinit var binding:ActivityTypeDescBinding
private lateinit var viewModel: MainViewModel
private lateinit var adapter:MoreAndSearchAdapter
private var currentTitleName: String = ""
companion object{
var titleName:String="name"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding=ActivityTypeDescBinding.inflate(layoutInflater)
init()
setContentView(binding.root)
}
private fun init(){
showTPAD(this) { null }
viewModel=ViewModelProvider(this)[MainViewModel::class.java]
currentTitleName = intent?.getStringExtra(titleName) ?: "Default Title"
// 保存标题到ViewModel
viewModel.currentTitleName = currentTitleName
// 设置标题 - 从ViewModel获取确保数据持久化
binding.name.text = viewModel.currentTitleName ?: currentTitleName
binding.searchPb.visibility= View.VISIBLE
binding.imageBack.setOnClickListener { finish() }
adapter=MoreAndSearchAdapter()
adapter.setListener(this)
binding.list.layoutManager=GridLayoutManager(this,2)
binding.list.adapter=adapter
viewModel.classificationList.observe(this) { list ->
// 在这里处理返回的数据
if(list.isNotEmpty()){
updateUI(list)
}
}
if(viewModel.classificationList.value.isNullOrEmpty()){
Log.d("Therererer","startGet")
viewModel.getClassificationList(currentTitleName)
}
}
private fun updateUI(list: List<Photo>){
Log.d("MorePhotoActivity","list size is"+list.size.toString())
adapter.setList(list)
binding.searchPb.visibility= View.GONE
adapter.notifyDataSetChanged()
}
override fun inItemClick(paper: Photo) {
showTPAD(this) {
val intent= Intent(this,StartDownApplyActivity::class.java)
intent.putExtra(StartDownApplyActivity.paperKey,paper)
startActivity(intent)
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0%"
android:toYDelta="100%"
android:duration="300"/>
</set>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0%"
android:duration="300"/>
</set>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M667.8,117.3C832.9,117.3 938.7,249.7 938.7,427.9c0,138.3 -125.1,290.5 -371.6,461.6a96.8,96.8 0,0 1,-110.2 0C210.4,718.4 85.3,566.1 85.3,427.9 85.3,249.7 191.1,117.3 356.2,117.3c59.6,0 100.1,20.8 155.8,68.1C567.7,138.2 608.2,117.3 667.8,117.3z"
android:fillColor="#C03B3B"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M704,128C833.6,128 938.7,234.7 938.7,384c0,298.7 -320,469.3 -426.7,533.3C405.3,853.3 85.3,682.7 85.3,384c0,-149.3 106.7,-256 234.7,-256C399.4,128 469.3,170.7 512,213.3c42.7,-42.7 112.6,-85.3 192,-85.3zM551.9,793.8a1141.4,1141.4 0,0 0,103.3 -72.6C782.3,620.1 853.3,509.6 853.3,384c0,-100.7 -65.6,-170.7 -149.3,-170.7 -45.9,0 -95.6,24.3 -131.7,60.3L512,334l-60.3,-60.3C415.6,237.7 365.9,213.3 320,213.3 237.2,213.3 170.7,284 170.7,384c0,125.6 71.1,236.1 198.2,337.2 31.8,25.3 65.7,48.9 103.3,72.5 12.8,8.1 25.4,15.8 39.9,24.4 14.5,-8.6 27.1,-16.3 39.9,-24.4z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:bottomRightRadius="10dp" android:bottomLeftRadius="10dp"/>
<solid android:color="@color/colorSelect"/>
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorSelect"/>
</shape>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 线性渐变配置 -->
<gradient
android:type="linear"
android:startColor="@color/colorSelect"
android:endColor="@color/colorSelect"
android:angle="315"
/>
<corners android:radius="50dp"/>
</shape>

View File

@ -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:angle="90"
android:startColor="#80000000"
android:centerColor="#00000000"
android:endColor="#80000000"
android:type="linear" />
</shape>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 线性渐变配置 -->
<gradient
android:type="linear"
android:startColor="@color/white"
android:endColor="@color/white"
android:angle="0"
/>
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
</shape>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M747.2,283.2L54.5,283.2v692.7h692.7v-692.7zM656.8,373.6v512h-512v-512h512z"
android:fillColor="@color/colorSelect"/>
<path
android:pathData="M993.3,12.4v692.7h-287.2v-90.4h196.8v-512h-512v224.4h-90.4V12.4z"
android:fillColor="@color/colorSelect"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/colorSelect"
android:pathData="M426.9,683l170.8,0c25.6,0 42.7,-17.1 42.7,-42.7L640.3,512.3c0,-25.6 -17.1,-42.7 -42.7,-42.7l0,-42.7c0,-47 -38.4,-85.4 -85.4,-85.4s-85.4,38.4 -85.4,85.4l0,42.7c-25.6,0 -42.7,17.1 -42.7,42.7l0,128.1C384.2,666 401.3,683 426.9,683zM461,426.9c0,-29.9 21.3,-51.2 51.2,-51.2s51.2,21.3 51.2,51.2l0,42.7 -102.5,0L461,426.9 461,426.9zM725.7,42.7 L298.8,42.7c-47,0 -85.4,38.4 -85.4,85.4l0,768.4c0,47 38.4,85.4 85.4,85.4l426.9,0c47,0 85.4,-38.4 85.4,-85.4L811.1,128.1C811.1,81.1 772.7,42.7 725.7,42.7zM725.7,811.1 L298.8,811.1 298.8,213.4l426.9,0L725.7,811.1z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/colorSelect"
android:pathData="M776.7,1010.1h-479.9c-28.3,0 -51.3,-23 -51.3,-51.3v-891.1c0,-28.3 23,-51.3 51.3,-51.3h479.9c28.3,0 51.3,23 51.3,51.3v891.1c0,28.3 -23,51.3 -51.3,51.3v0zM536.6,958.8c19.1,0 34.2,-15.4 34.2,-34.2s-15.4,-34.2 -34.2,-34.2 -34.2,15.4 -34.2,34.2 15.4,34.2 34.2,34.2v0zM776.7,119h-479.9v719.7h479.6v-719.7h0.3z"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M222.1,580.4a356.2,356.2 0,0 0,34.1 152.9,357.6 357.6,0 0,0 477.7,-477.7A357.6,357.6 0,0 0,222.1 580.4z"
/>
<path
android:pathData="M1009,936.6l-276.1,-276.1a409.5,409.5 0,1 0,-72.3 72.3l276.1,276.1a51.2,51.2 0,0 0,72.3 -72.3zM409.8,716.9a307.1,307.1 0,1 1,307.1 -307.1,307.1 307.1,0 0,1 -307.1,307.1z"
android:fillColor="@color/colorSelect"/>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="20dp" android:topRightRadius="20dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
<solid android:color="@color/colorSecondBg"/>
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/select_gall_11" android:state_selected="true" />
<item android:drawable="@drawable/select_gall_00" />
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/select_like_11" android:state_selected="true" />
<item android:drawable="@drawable/select_like_00" />
</selector>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View 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>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M395.2,513.6l-323.1,-312.4c-19.1,-18.4 -19.1,-48.3 0,-66.7 19.1,-18.4 49.9,-18.4 69,0L498.6,480.3c19.1,18.4 19.1,48.3 0,66.7l-357.6,345.7c-9.5,9.2 -22,13.8 -34.5,13.8 -12.5,0 -25,-4.6 -34.5,-13.8 -19.1,-18.4 -19.1,-48.2 0,-66.7L395.2,513.6z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dp" />
<solid android:color="@color/colorNotSelect" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dp" />
<gradient
android:angle="0"
android:endColor="@color/white"
android:centerColor="@color/white"
android:startColor="@color/white" />
</shape>
</clip>
</item>
</layer-list>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:topLeftRadius="10dp" android:topRightRadius="10dp"/>
<solid android:color="@color/white"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M878.6,337.2a57.8,57.8 0,0 0,-81.7 0L574.6,559.5V173a57.8,57.8 0,0 0,-115.6 0v386.5L236.8,337.2a57.8,57.8 0,0 0,-81.7 0,57.8 57.8,0 0,0 0,81.8l318.7,318.7a57.6,57.6 0,0 0,40.9 16.9c0.7,0 1.5,-0.1 2.2,-0.1 0.7,0 1.5,0.1 2.2,0.1a57.6,57.6 0,0 0,40.9 -16.9L878.6,419a57.8,57.8 0,0 0,0 -81.8zM861,908.4H165.4a57.8,57.8 0,0 1,0 -115.6h695.6a57.8,57.8 0,0 1,0 115.6z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M154.5,469.3H981.3a42.7,42.7 0,1 1,0 85.3H154.5l300.7,266.9a42.7,42.7 0,1 1,-57.1 63.4l-384,-341.3a42.7,42.7 0,0 1,0 -63.4l384,-341.3a42.7,42.7 0,1 1,57.1 63.4L154.5,469.3z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/add_to_already" android:state_selected="true" />
<item android:drawable="@drawable/add_to_like" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="50dp"/>
<stroke android:color="@color/colorSecondBg" android:width="1dp"/>
</shape>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M555.5,118l312.9,224.6A117.3,117.3 0,0 1,917.3 437.9V800c0,64.8 -52.5,117.3 -117.3,117.3H640V746.7c0,-70.7 -57.3,-128 -128,-128s-128,57.3 -128,128v170.7H224c-64.8,0 -117.3,-52.5 -117.3,-117.3V437.9a117.3,117.3 0,0 1,48.9 -95.3l312.9,-224.6a74.7,74.7 0,0 1,87.1 0z"
android:fillColor="@color/colorNotSelect"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M555.5,118l312.9,224.6A117.3,117.3 0,0 1,917.3 437.9V800c0,64.8 -52.5,117.3 -117.3,117.3H640V746.7c0,-70.7 -57.3,-128 -128,-128s-128,57.3 -128,128v170.7H224c-64.8,0 -117.3,-52.5 -117.3,-117.3V437.9a117.3,117.3 0,0 1,48.9 -95.3l312.9,-224.6a74.7,74.7 0,0 1,87.1 0z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M667.8,117.3C832.9,117.3 938.7,249.7 938.7,427.9c0,138.3 -125.1,290.5 -371.6,461.6a96.8,96.8 0,0 1,-110.2 0C210.4,718.4 85.3,566.1 85.3,427.9 85.3,249.7 191.1,117.3 356.2,117.3c59.6,0 100.1,20.8 155.8,68.1C567.7,138.2 608.2,117.3 667.8,117.3z"
android:fillColor="@color/colorNotSelect"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M667.8,117.3C832.9,117.3 938.7,249.7 938.7,427.9c0,138.3 -125.1,290.5 -371.6,461.6a96.8,96.8 0,0 1,-110.2 0C210.4,718.4 85.3,566.1 85.3,427.9 85.3,249.7 191.1,117.3 356.2,117.3c59.6,0 100.1,20.8 155.8,68.1C567.7,138.2 608.2,117.3 667.8,117.3z"
android:fillColor="@color/white"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="@color/white"
android:pathData="M261.9,492.9c20.6,11.9 46,11.9 66.6,0 20.6,-11.9 33.3,-33.9 33.3,-57.6 0,-36.8 -29.8,-66.5 -66.6,-66.5s-66.5,29.8 -66.5,66.5c0,23.8 12.7,45.7 33.2,57.6z"/>
<path
android:fillColor="@color/white"
android:pathData="M804,153.4L221.4,153.4c-78.3,0 -142,63.7 -142,142v436.9c0,78.3 63.7,142 142,142L804,874.3c78.3,0 142,-63.7 142,-142L946,295.4c-0.1,-78.3 -63.7,-142 -142,-142zM144.9,295.4c0,-42.2 34.3,-76.5 76.4,-76.5L804,218.9c42.1,0 76.4,34.3 76.4,76.5v331.1l-95.3,-86.2 -13.6,-9.7c-71.9,-46.1 -164.2,-45.1 -233.9,1.3l-385,232.6c-4.7,-9.9 -7.7,-20.6 -7.7,-32.2L144.9,295.4zM804,808.8L221.4,808.8c-4.1,0 -7.6,-1.7 -11.4,-2.3l362.8,-219.2c49.5,-32.9 113.6,-33.4 162.8,-1.9l143.7,128.5 1.2,-1.3v19.8c-0.1,42.1 -34.4,76.4 -76.5,76.4z"/>
</vector>

View File

@ -0,0 +1,142 @@
<?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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".BasicActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingVertical="20dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="24sp"
android:textStyle="bold"
android:layout_marginStart="20dp"
android:textColor="@color/black"/>
<RelativeLayout
android:id="@+id/rlSearch"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp"
android:background="@drawable/search_stroke"
android:layout_marginEnd="20dp"
android:layout_marginStart="10dp"
android:descendantFocusability="blocksDescendants"
android:layout_gravity="center">
<ImageView
android:id="@+id/imgSearch"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/search_grey"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorNotSelect"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/imgSearch"
android:textSize="16sp"
android:ellipsize="end"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_marginStart="10dp"
android:text="@string/to_search"/>
</RelativeLayout>
</LinearLayout>
<FrameLayout
android:id="@+id/fragmentIn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:id="@+id/llBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:background="@drawable/main_bottom"
app:layout_constraintBottom_toBottomOf="parent"
android:elevation="10dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llHome"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingVertical="8dp"
android:layout_weight="1"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<View
android:id="@+id/view1"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/brown_oval"
android:visibility="visible"
/>
<ImageView
android:id="@+id/imgHome"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:src="@drawable/home_select_0" />
</RelativeLayout>
<TextView
android:id="@+id/tvStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorNotSelect"
android:text="@string/classification"/>
</LinearLayout>
<LinearLayout
android:id="@+id/llLike"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingVertical="10dp"
android:layout_weight="1"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<View
android:id="@+id/view2"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/brown_oval"
android:visibility="invisible"
/>
<ImageView
android:id="@+id/imgLike"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:src="@drawable/home_select_1" />
</RelativeLayout>
<TextView
android:id="@+id/tvEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorNotSelect"
android:text="@string/like"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,115 @@
<?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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".view.FindByNameActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageBack"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_gravity="center"
android:padding="13dp"
android:src="@drawable/p_finish"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/black" />
<RelativeLayout
android:id="@+id/rlSearch"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/search_stroke"
android:layout_marginHorizontal="10dp"
android:gravity="center"
android:layout_gravity="center">
<ImageView
android:id="@+id/imgSearch"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/e_find_ic"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"/>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/imgSearch"
android:textSize="16sp"
android:imeOptions="actionSearch"
android:background="@null"
android:maxLines="1"
android:inputType="text"
android:layout_marginEnd="60dp"
android:textColorHint="@color/colorNotSelect"
android:layout_marginStart="10dp"
android:hint="@string/to_search"/>
<TextView
android:id="@+id/tvStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5sp"
android:text="@string/start"
android:textSize="16sp"
android:visibility="gone"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:textColor="@color/black"
/>
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginHorizontal="10dp"
android:background="@drawable/d_top_10_radius_bg">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginHorizontal="5dp" />
<LinearLayout
android:id="@+id/empty_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/none" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/no_data_found"
android:textColor="#000000" />
</LinearLayout>
<ProgressBar
android:id="@+id/searchPb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateTint="@color/colorSelect"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,126 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/bg_placeholder"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageBack"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:padding="13dp"
android:background="@drawable/brown_oval"
android:src="@drawable/p_finish"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<RelativeLayout
android:id="@+id/layoutSet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/button_bg"
android:paddingVertical="5dp"
android:layout_marginEnd="20dp"
android:paddingHorizontal="5dp">
<TextView
android:id="@+id/txApply"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/apply"
android:textColor="@color/white"
android:layout_centerVertical="true"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginVertical="5dp"
android:layout_marginHorizontal="20dp"/>
<ProgressBar
android:id="@+id/pbSet"
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_centerInParent="true"
android:indeterminateTint="@color/white"
android:padding="13dp"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/tvContent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageLike"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/brown_oval"
android:padding="13dp"
android:layout_marginBottom="20dp"
android:src="@drawable/p_like_ic" />
<RelativeLayout
android:id="@+id/layout_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:background="@drawable/brown_oval">
<ImageView
android:id="@+id/imageDownload"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerInParent="true"
android:padding="13dp"
android:src="@drawable/p_down_ic" />
<ProgressBar
android:id="@+id/pb_download"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerInParent="true"
android:indeterminateTint="@color/white"
android:padding="13dp"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
<TextView
android:id="@+id/tvContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="40dp"
android:padding="10dp"
android:text="@string/app_name"
android:textColor="@color/colorNotSelect"
android:textSize="17sp"
android:textStyle="bold"
android:background="#1ab59a82"
android:layout_marginBottom="150dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorSelect"
tools:context=".view.StartProgressActivity">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/imageview_logo"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="260dp"
android:src="@mipmap/ic_launcher_round"
app:roundPercent="0.2" />
<TextView
android:id="@+id/tvLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/imageview_logo"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:text="@string/app_name"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="22sp"/>
<ProgressBar
android:id="@+id/progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_centerHorizontal="true"
android:layout_below="@+id/tvLogo"
android:layout_marginHorizontal="20dp"
android:max="100"
android:layout_marginTop="34dp"
android:progress="80"
android:indeterminateTint="@color/white"
android:progressDrawable="@drawable/l_progress_bg_grey" />
</RelativeLayout>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".view.MorePhotoActivity">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/imageBack"
android:layout_alignBottom="@id/imageBack"
android:layout_centerHorizontal="true"
android:gravity="center"
android:paddingTop="20dp"
android:text="@string/app_name"
android:background="@drawable/bottom_radius_20_bg"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/imageBack"
android:layout_width="45dp"
android:layout_height="65dp"
android:layout_gravity="center"
android:paddingBottom="13dp"
android:paddingTop="30dp"
android:src="@drawable/p_finish"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginHorizontal="10dp"
android:layout_below="@id/imageBack" />
<ProgressBar
android:id="@+id/searchPb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateTint="@color/white"
android:visibility="gone" />
</RelativeLayout>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.ClassificationFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rvView"/>
</RelativeLayout>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/d_top_10_radius_bg"
android:orientation="vertical"
android:paddingVertical="20dp">
<LinearLayout
android:id="@+id/layout_home"
android:layout_width="match_parent"
android:layout_height="64dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/dialog_select_ic_3" />
<TextView
android:id="@+id/home"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
android:text="@string/apply_to_desktop"
android:textColor="@color/colorSelect"
android:textSize="15sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="10dp"
android:background="@color/white" />
<LinearLayout
android:id="@+id/layout_lock"
android:layout_width="match_parent"
android:layout_height="64dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/dialog_select_ic_2" />
<TextView
android:id="@+id/lock"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="22dp"
android:text="@string/apply_to_lock_screen"
android:textColor="@color/colorSelect"
android:textSize="15sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="10dp"
android:background="@color/white" />
<LinearLayout
android:id="@+id/layout_both"
android:layout_width="match_parent"
android:layout_height="64dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/dialog_select_ic_1" />
<TextView
android:id="@+id/both"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_marginStart="22dp"
android:text="@string/apply_to_all"
android:textColor="@color/colorSelect"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.LikeFragment">
<TextView
android:id="@+id/txTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="8dp"
android:layout_marginStart="20dp"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="@color/colorSelect"
android:text="@string/like"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/txTitle"
android:layout_marginHorizontal="5dp"
android:id="@+id/rvView"/>
<LinearLayout
android:id="@+id/layout_no_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:src="@drawable/none" />
<TextView
android:id="@+id/tvNoData"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:lineSpacingExtra="4dp"
android:text="@string/empty"
android:textColor="@color/colorSelect"
android:layout_marginBottom="50dp"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,37 @@
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="5dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="150dp">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:src="@mipmap/bg_placeholder" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:background="@drawable/d_black_trans_bg" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="5dp"
android:text="@string/app_name"
android:textColor="@color/colorSelect"
android:maxLines="1"
android:ellipsize="end"
android:textSize="15sp" />
</LinearLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:id="@+id/llView"
android:layout_marginBottom="15dp"
android:layout_marginHorizontal="20dp"
android:background="@drawable/each_top_radius_50"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingHorizontal="10dp"
android:paddingVertical="20dp"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"/>
<TextView
android:id="@+id/txTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginEnd="10dp"
android:textColor="@color/colorSelect"/>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/img_go_in_ic"
android:padding="3dp"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:id="@+id/rvView"/>
</LinearLayout>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginHorizontal="5dp"
android:orientation="horizontal"
android:layout_height="wrap_content">
<View
android:id="@+id/start"
android:layout_width="5dp"
android:layout_height="1dp"
android:visibility="gone"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<androidx.cardview.widget.CardView
android:layout_width="130dp"
android:layout_height="200dp"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/inImage"
android:layout_width="130dp"
android:layout_height="200dp"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
</RelativeLayout>
<View
android:id="@+id/end"
android:layout_width="5dp"
android:layout_height="1dp"
android:visibility="gone"/>
</LinearLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
android:layout_margin="5dp"
app:cardCornerRadius="10dp">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="@mipmap/bg_placeholder" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/d_black_trans_bg" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginHorizontal="10dp"
android:layout_marginBottom="10dp"
android:text="@string/app_name"
android:textColor="@color/white"
android:maxLines="1"
android:ellipsize="end"
android:textSize="15sp" />
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,5 @@
<?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="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Some files were not shown because too many files have changed in this diff Show More