初始化提交

This commit is contained in:
renhaoting 2025-11-18 13:30:49 +08:00
parent 0d221594d1
commit 76bb6e3e42
279 changed files with 11386 additions and 0 deletions

1
app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

91
app/build.gradle Normal file
View File

@ -0,0 +1,91 @@
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.hilt)
// alias(libs.plugins.ksp)
alias(libs.plugins.protobuf)
id 'kotlin-kapt'
}
android {
namespace = "com.gamedog.vididin"
compileSdk libs.versions.compileSdk.get().toInteger()
defaultConfig {
applicationId "com.gamedog.vididin"
minSdk libs.versions.minSdk.get().toInteger()
targetSdk libs.versions.targetSdk.get().toInteger()
versionCode libs.versions.versionCode.get().toInteger()
versionName libs.versions.versionName.get().toString()
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility libs.versions.javaVersion.get().toInteger()
targetCompatibility libs.versions.javaVersion.get().toInteger()
}
kotlinOptions {
jvmTarget = libs.versions.javaVersion.get().toInteger()
}
buildFeatures {
viewBinding = true
}
}
protobuf {
protoc {
artifact = libs.protobuf.protoc.get().toString()
}
generateProtoTasks {
all().forEach { task ->
task.builtins {
register("java") {
option("lite")
}
register("kotlin") {
option("lite")
}
}
}
}
}
dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation(project(":core:network"))
implementation(project(":core:architecture"))
//api(project(":core:architecture-reflect"))
implementation(project(":core:network"))
implementation libs.androidx.navigation.fragment.ktx
implementation(libs.startup)
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
//ksp(libs.hilt.compiler)
implementation(libs.material)
implementation(libs.datastore)
implementation(libs.protobuf.kotlin.lite)
implementation(libs.kotlinx.serialization.json)
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:13.0.0'
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:custom-ui:13.0.0'
implementation(libs.glide) // ImageLoader在用
implementation(libs.okhttp.logging)
implementation(libs.retrofit)
implementation(libs.retrofit.kotlin.serialization)
}

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,39 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/Theme.Architectureandroid">
<activity
android:name=".main.MainActivity"
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=".login.LoginActivity" android:exported="false" />
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false" >
<meta-data
android:name="com.gamedog.vididin.router.RouterInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>

View File

@ -0,0 +1,8 @@
package com.gamedog.vididin
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class App : Application()

View File

@ -0,0 +1,16 @@
package com.gamedog.vididin
/**
* 描述网络常量
*
*/
const val URL_YOUTUBE_API = "https://www.googleapis.com"
/**
* 描述其他常量
*
*/
const val XXXX = "xxx"

View File

@ -0,0 +1,174 @@
package com.gamedog.vididin.adapter
import android.content.Context
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.widget.ViewPager2
import com.ama.core.architecture.appBase.adapter.AppNavigatorAdapter
import com.ama.core.common.util.asSafe
import com.ama.core.common.util.getDataFromThemeAttr
import com.gamedog.vididin.R
import com.gamedog.vididin.beans.MainTabsItem
import com.gamedog.vididin.main.interfaces.OnTabClickAgainListener
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshFinishListener
import com.gamedog.vididin.main.interfaces.OnTabClickRefreshListener
import net.lucode.hackware.magicindicator.MagicIndicator
import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator
import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView
import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.CommonPagerTitleView
import kotlin.ranges.until
import com.gamedog.vididin.databinding.ItemActivityMainTabBinding as ViewBinding
import com.google.android.material.R as materialR
class MainTabsAdapter(
private val activity: FragmentActivity,
private val viewPager2: ViewPager2,
private val mainFragmentStateAdapter: MainViewPagerAdapter,
private val magicIndicator: MagicIndicator,
) : AppNavigatorAdapter<MainTabsItem>() {
companion object {
val TEXT_TAB = 1
val IMAGE_TAB = 2
}
private var isDarkFont: Boolean = true
override fun getTabView(context: Context, index: Int, item: MainTabsItem): IPagerTitleView {
val tabView = CommonPagerTitleView(context)
val binding = ViewBinding.inflate(LayoutInflater.from(context))
binding.setTabStyle(IMAGE_TAB)
tabView.setContentView(binding.root)
tabView.setColor(isDarkFont, index == viewPager2.currentItem)
tabView.updateImageSrc(false, item)
tabView.setOnClickListener {
binding.onTabClickHandle(index, item)
}
tabView.onPagerTitleChangeListener = object: CommonPagerTitleView.OnPagerTitleChangeListener {
override fun onSelected(index: Int, totalCount: Int) {
tabView.updateImageSrc(true, item)
}
override fun onDeselected(index: Int, totalCount: Int) {
tabView.updateImageSrc(false, item)
}
override fun onLeave(
index: Int,
totalCount: Int,
leavePercent: Float,
leftToRight: Boolean
) {
}
override fun onEnter(
index: Int,
totalCount: Int,
enterPercent: Float,
leftToRight: Boolean
) {
}
}
return tabView
}
override fun getIndicator(context: Context): IPagerIndicator? = null
private fun ViewBinding.onTabClickHandle(index: Int, item: MainTabsItem) {
if (viewPager2.currentItem == index) {
onTabClickAgainHandle(index)
} else {
val isNeedLogin = false
if (!isNeedLogin) {
viewPager2.setCurrentItem(index, false)
} else {
/*LoginManager.checkLogin(activity) {
viewPager2.setCurrentItem(index, false)
}*/
}
}
}
private fun ViewBinding.onTabClickAgainHandle(index: Int) {
val currentFragment = mainFragmentStateAdapter.getFragmentByIndex(index)
if (currentFragment is OnTabClickRefreshListener) {
// 刷新 - 展示Loading
currentFragment.onTabClickRefresh(object : OnTabClickRefreshFinishListener {
override fun onTabClickRefreshFinish() {
setTabStyle(1)
}
})
} else if (currentFragment is OnTabClickAgainListener) {
currentFragment.onTabClickAgain()
}
}
private fun ViewBinding.setTabStyle(type: Int) {
when (type) {
TEXT_TAB -> {
title.isVisible = true
image.isVisible = false
}
IMAGE_TAB -> {
title.isVisible = false
image.isVisible = true
}
}
}
fun setIsDarkFont(isDarkFont: Boolean) {
this.isDarkFont = isDarkFont
setTitleColor(isDarkFont)
setBackgroundColor(isDarkFont)
}
private fun setTitleColor(isDarkFont: Boolean) {
val titleContainer =
magicIndicator.navigator.asSafe<CommonNavigator>()?.titleContainer ?: return
for (i in 0 until titleContainer.childCount) {
titleContainer.getChildAt(i).asSafe<CommonPagerTitleView>()
?.setColor(isDarkFont, i == viewPager2.currentItem)
}
}
private fun CommonPagerTitleView.setColor(
isDarkFont: Boolean,
selected: Boolean,
) {
val title = findViewById<TextView>(R.id.title)
title.alpha = if (selected) 1f else 0.7f
title.setTextColor(context.getDataFromThemeAttr(if (isDarkFont) materialR.attr.colorOnSurface else materialR.attr.colorOnSurfaceInverse))
}
private fun CommonPagerTitleView.updateImageSrc(
selected: Boolean,
tabItem: MainTabsItem
) {
val image = findViewById<ImageView>(R.id.image)
image.setImageResource(if (selected) tabItem.tabIconSelected else tabItem.tabIconNormal)
}
private fun setBackgroundColor(
isDarkFont: Boolean,
) {
val selectedBackgroundColor =
magicIndicator.context.getDataFromThemeAttr(if (isDarkFont) materialR.attr.colorSurface else materialR.attr.colorSurfaceInverse)
magicIndicator.setBackgroundColor(selectedBackgroundColor)
}
}

View File

@ -0,0 +1,21 @@
package com.gamedog.vididin.adapter
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.ama.core.architecture.appBase.adapter.AppFragmentStateAdapter
import com.gamedog.vididin.beans.MainTabsItem
import com.gamedog.vididin.repository.MainTabType
import com.gamedog.vididin.router.Router
class MainViewPagerAdapter(activity: FragmentActivity) :
AppFragmentStateAdapter<MainTabsItem>(activity, true) {
override fun createFragment(position: Int, item: MainTabsItem): Fragment {
return when (item.type) {
MainTabType.HOME -> Router.Home.createHomeFragment()
MainTabType.TASKS -> Router.Task.createTaskFragment()
MainTabType.MINE -> Router.Mine.createMineFragment()
}
}
}

View File

@ -0,0 +1,48 @@
package com.gamedog.vididin.feature.home.api
import com.gamedog.vididin.beans.ResYoutubeChannel
import com.gamedog.vididin.beans.ResYoutubePlayList
import retrofit2.http.GET
import retrofit2.http.Query
import java.net.URLEncoder
interface YoutubeApi {
/**
* Youtube channel list
*/
@GET("/youtube/v3/channels")
suspend fun getChannelList(
@Query("part") part: String="snippet",
@Query("key") key: String="AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY",
@Query("channelId") channelId: String="UCbTLwN10NoCU4WDzLf1JMOA",
): ResYoutubeChannel
/**
* Youtube play list
*/
@GET("/youtube/v3/playlists")
suspend fun getPlayList(
@Query("part") part: String="snippet",
@Query("key") key: String="AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY",
@Query("channelId") channelId: String="UCbTLwN10NoCU4WDzLf1JMOA",
): ResYoutubePlayList
@GET("/youtube/v3/playlistItems")
suspend fun getVideoList(
@Query("part") part: String= URLEncoder.encode("id", "UTF-8"),
@Query("key") key: String="AIzaSyBm9k2lS_j7Fdd43NEPkcfikJRotup5DMY",
@Query("playlistId") channelId: String="PLcVfz1-_0rj_KFKlQeW2ZJnWTSjgc-9Jp",
//@Query("pageToken") pageToken: String=""
): ResYoutubePlayList
}

View File

@ -0,0 +1,24 @@
package com.gamedog.vididin.beans
import com.ama.core.common.util.asUnsafe
import com.ama.core.model.BaseFragmentStateDiffItem
import com.gamedog.vididin.repository.MainTabType
data class MainTabsItem(
val titleResId: Int,
val type: MainTabType,
val tabIconNormal: Int,
val tabIconSelected: Int,
val updateMainTabShopOrFriend: (Boolean) -> Unit,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = type
override fun <T> areContentsTheSame(newItem: T): Boolean {
val mainTabsItem = newItem.asUnsafe<MainTabsItem>()
return titleResId == mainTabsItem.titleResId && type == mainTabsItem.type
}
override fun getItemId() = type.ordinal.toLong()
}

View File

@ -0,0 +1,9 @@
package com.gamedog.vididin.beans
data class User(
val id: Int,
val token: String,
val account: String,
val createdAt: String,
)

View File

@ -0,0 +1,9 @@
package com.gamedog.vididin.beans
data class UserData(
val user: User,
val mainTabs: List<Int>,
val homeTabs: List<Int>,
val useDynamicColor: Boolean,
)

View File

@ -0,0 +1,122 @@
package com.gamedog.vididin.beans
import com.ama.core.model.BaseFragmentStateDiffItem
import kotlinx.serialization.Serializable
@Serializable
data class ResYoutubeChannel(
val id: String,
val name: String,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = id
override fun getItemId() = id.hashCode().toLong()
}
@Serializable
data class ResYoutubePlayList (
val kind: String,
val etag: String, // TODO - this is Etag type
val nextPageToken: String,
val prevPageToken: String,
val pageInfo: PageInfo,
val items: List<YoutubeVideo>,
) /*: BaseFragmentStateDiffItem {
override fun getPrimaryKey() = pageInfo
override fun getItemId() = pageInfo.hashCode().toLong()
}*/
@Serializable
data class PageInfo(
val totalResults: Int,
val resultsPerPage: Int,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = totalResults
override fun getItemId() = totalResults.hashCode().toLong()
}
@Serializable
data class YoutubeVideo(
val kind: String,
val etag: String,
val id: String,
val snippet: Snippet,
val status: Status,
val contentDetails: ContentDetails,
val player: Player,
val localizations: Localizations,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = id
override fun getItemId() = id.hashCode().toLong()
}
@Serializable
data class ContentDetails(
val itemCount: Int,
): BaseFragmentStateDiffItem {
override fun getPrimaryKey() = itemCount
override fun getItemId() = itemCount.hashCode().toLong()
}
@Serializable
data class Player(
val embedHtml: String,
): BaseFragmentStateDiffItem {
override fun getPrimaryKey() = embedHtml
override fun getItemId() = embedHtml.hashCode().toLong()
}
@Serializable
data class Localizations(
val title: String,
val description: String,
): BaseFragmentStateDiffItem {
override fun getPrimaryKey() = title
override fun getItemId() = title.hashCode().toLong()
}
@Serializable
data class Snippet(
val publishedAt: String,
val channelId: String,
val title: String,
val description: String,
val thumbnails: String, //
val channelTitle: String,
val defaultLanguage: String,
val localized: Localized,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = channelId
override fun getItemId() = channelId.hashCode().toLong()
}
@Serializable
data class Localized(
val title: String,
val description: String,
) : BaseFragmentStateDiffItem {
override fun getPrimaryKey() = title
override fun getItemId() = title.hashCode().toLong()
}
@Serializable
data class Status(
val privacyStatus: String,
val podcastStatus: Int,
): BaseFragmentStateDiffItem {
override fun getPrimaryKey() = podcastStatus
override fun getItemId() = privacyStatus.hashCode().toLong()
}

View File

@ -0,0 +1,13 @@
package com.gamedog.vididin.di
import javax.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class Dispatcher(val appDispatcher: AppDispatchers)
enum class AppDispatchers {
Default,
IO,
}

View File

@ -0,0 +1,29 @@
package com.gamedog.vididin.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import javax.inject.Qualifier
import javax.inject.Singleton
@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class ApplicationScope
@Module
@InstallIn(SingletonComponent::class)
internal object CoroutineScopesModule {
@Provides
@Singleton
@ApplicationScope
// 提供全局协程作用域
fun providesCoroutineScope(
@Dispatcher(AppDispatchers.Default) dispatcher: CoroutineDispatcher,
): CoroutineScope = CoroutineScope(SupervisorJob() + dispatcher)
}

View File

@ -0,0 +1,18 @@
package com.gamedog.vididin.di
import com.gamedog.vididin.repository.DefaultMainRepository
import com.gamedog.vididin.repository.MainRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface DataModule {
@Binds
fun bindsMainRepository(repository: DefaultMainRepository): MainRepository
}

View File

@ -0,0 +1,100 @@
package com.gamedog.vididin.core.network.di
import android.util.Log
import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.asResponseBody
import okio.Buffer
import java.io.IOException
import java.util.Locale
class GlobalInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val bodyStr = readBody(chain.request().body)
val emptyBody = "{}".toRequestBody("application/json;charset=utf-8".toMediaType())
val requestBody = if (bodyStr.isNotBlank()) request.body else emptyBody
val headersBuilder = Headers.Builder()
/*
.add("authorazation", "Bearer xxxxx")
.add("AUTH_DID", AppUtils.getAndroidID())
.add("platform", AppConstant.APP_CLIENT)
.add("Authorization", "Bearer xxx")
.add("versionNum", "100")
*/
.add("User-Agent", "Android")
.add("Accept-Language", Locale.getDefault().toLanguageTag())
.add("Content-Type", "application/json")
.add("Accept", "application/json")
.add("Accept-Charset", "utf-8")
val headers = headersBuilder.build()
request = chain.request().newBuilder()
.headers(headers)
.build()
val response = chain.proceed(request)
if (true) {
try {
Log.d("RetroLog" ,
"""
发起请求 我是开始分割线
${request.url}
******** 请求头 ${request.method} ********
${getRequestHeadersString(request)}
******** 请求体(当post等时) ********
${readBody(requestBody)}
******** 请求响应 ********
${clone(response.body)?.string()}
我是结束分割线
""".trimIndent()
)
} catch (e: Exception) {
Log.d("RetroLog" , "GlobalInterceptor request.exception : ${e.localizedMessage}}")
}
}
return response
}
fun getRequestHeadersString(request: Request): String {
val headers = request.headers
val headerCount = headers.size
val sb = StringBuilder()
for (i in 0 until headerCount) {
val key = headers.name(i)
val value = headers.value(i)
sb.append("$key=$value\n")
}
return sb.toString()
}
private fun readBody(body: RequestBody?): String {
val buffer = Buffer()
body?.writeTo(buffer)
return buffer.readUtf8()
}
@Throws(IOException::class)
private fun clone(body: ResponseBody?): ResponseBody? {
val source = body?.source()
if (source?.request(Long.MAX_VALUE) == true) throw IOException("body too long!")
val bufferedCopy = source?.buffer?.clone()
return bufferedCopy?.asResponseBody(body.contentType(), body.contentLength())
}
}

View File

@ -0,0 +1,71 @@
package com.gamedog.vididin.di
import com.gamedog.vididin.core.router.interfaces.HomeRouter
import com.gamedog.vididin.core.router.interfaces.LoginRouter
import com.gamedog.vididin.core.router.interfaces.MineRouter
import com.gamedog.vididin.core.router.interfaces.TaskRouter
import com.gamedog.vididin.feature.home.repository.DefaultYoutubeDatasource
import com.gamedog.vididin.feature.home.repository.DefaultYoutubeRepository
import com.gamedog.vididin.main.fragments.home.YoutubeDataSource
import com.gamedog.vididin.main.fragments.home.YoutubeRepository
import com.gamedog.vididin.router.DefaultHomeRouter
import com.gamedog.vididin.router.DefaultLoginRouter
import com.gamedog.vididin.router.DefaultMineRouter
import com.gamedog.vididin.router.DefaultTaskRouter
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object HomeModule {
@Provides
@Singleton
fun providesHomeRouter(): HomeRouter = DefaultHomeRouter()
}
@Module
@InstallIn(SingletonComponent::class)
object TaskModule {
@Provides
@Singleton
fun providesTaskRouter(): TaskRouter = DefaultTaskRouter()
}
@Module
@InstallIn(SingletonComponent::class)
object MineModule {
@Provides
@Singleton
fun providesMineRouter(): MineRouter = DefaultMineRouter()
}
@Module
@InstallIn(SingletonComponent::class)
internal interface YoutubeDataSourceModule {
@Binds
fun binds(impl: DefaultYoutubeDatasource): YoutubeDataSource
}
@Module
@InstallIn(SingletonComponent::class)
interface YoutubeRepositoryModule {
@Binds
fun bindsYoutubeRepository(repository: DefaultYoutubeRepository): YoutubeRepository
}
@Module
@InstallIn(SingletonComponent::class)
object LoginModule {
@Provides
@Singleton
fun providesLoginRouter(): LoginRouter = DefaultLoginRouter()
}

View File

@ -0,0 +1,60 @@
package com.gamedog.vididin.di
import com.gamedog.vididin.URL_YOUTUBE_API
import com.gamedog.vididin.core.network.di.GlobalInterceptor
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import okhttp3.Call
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object NetworkModule {
@Provides
@Singleton
fun providesNetworkJson(): Json = Json {
ignoreUnknownKeys = true
isLenient = true
}
@Provides
@Singleton
fun okHttpCallFactory(): Call.Factory =
OkHttpClient.Builder()
.addInterceptor(GlobalInterceptor())
/*.addInterceptor(
HttpLoggingInterceptor()
.apply {
if (BuildConfig.DEBUG) {
setLevel(HttpLoggingInterceptor.Level.BODY)
}
},
)*/
.build()
@Provides
@Singleton
fun providesRetrofit(
networkJson: Json,
okhttpCallFactory: dagger.Lazy<Call.Factory>,
): Retrofit {
return Retrofit.Builder()
.baseUrl(URL_YOUTUBE_API)
.callFactory { okhttpCallFactory.get().newCall(it) }
.addConverterFactory(
GsonConverterFactory.create()
//networkJson.asConverterFactory("application/json".toMediaType()),
)
.build()
}
}

View File

@ -0,0 +1,20 @@
package com.gamedog.vididin.di
import com.gamedog.vididin.core.router.interfaces.HomeRouter
import com.gamedog.vididin.core.router.interfaces.LoginRouter
import com.gamedog.vididin.core.router.interfaces.MineRouter
import com.gamedog.vididin.core.router.interfaces.TaskRouter
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@EntryPoint
@InstallIn(SingletonComponent::class)
interface RouterEntryPoint {
fun homeRouter(): HomeRouter
fun taskRouter(): TaskRouter
fun mineRouter(): MineRouter
fun loginRouter(): LoginRouter
}

View File

@ -0,0 +1,60 @@
package com.gamedog.vididin.login
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity
import com.gamedog.vididin.databinding.VididinappFeatureLoginActivityLoginBinding as ViewBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlin.jvm.java
@AndroidEntryPoint
@Suppress("DEPRECATION")
class LoginActivity : AppViewsEmptyViewModelActivity<ViewBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
/*Activity.overridePendingTransition(
designSystemR.anim.slide_in_bottom,
0
)*/
super.onCreate(savedInstanceState)
}
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
override fun ViewBinding.initWindowInsets() {
// 由于登录页面的子Fragment没有背景所以在此统一设置内间距即可实现子Fragment不需要实现。
ViewCompat.setOnApplyWindowInsetsListener(root) { v, insets ->
val systemBars = insets.getInsets(
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() or WindowInsetsCompat.Type.ime()
)
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
}
override fun ViewBinding.initViews() {
}
override fun ViewBinding.initListeners() {
}
override fun ViewBinding.initObservers() {
}
override fun finish() {
super.finish()
}
companion object {
internal fun startActivity(activity: Activity) {
activity.startActivity(Intent(activity.applicationContext, LoginActivity::class.java))
}
}
}

View File

@ -0,0 +1,7 @@
package com.gamedog.vididin.core.login.login
object LoginManager {
}

View File

@ -0,0 +1,122 @@
package com.gamedog.vididin.main
import com.ama.core.common.util.asSafe
import androidx.activity.OnBackPressedCallback
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
import androidx.viewpager2.widget.ViewPager2
import android.view.LayoutInflater
import androidx.activity.viewModels
import com.ama.core.architecture.appBase.AppViewsActivity
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
import com.ama.core.architecture.util.bindViewPager2
import com.ama.core.architecture.util.setCommonNavigator
import com.ama.core.architecture.util.setDataOrAdapter
import com.gamedog.vididin.adapter.MainTabsAdapter
import com.gamedog.vididin.adapter.MainViewPagerAdapter
import com.gamedog.vididin.main.interfaces.OnSwitchTabListener
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue
import com.gamedog.vididin.databinding.ActivityMainBinding as ViewBinding
import com.gamedog.vididin.main.MainUiState as UiState
import com.gamedog.vididin.main.MainViewModel as ViewModel
@AndroidEntryPoint
class MainActivity : AppViewsActivity<ViewBinding, UiState, ViewModel>(), OnTabStyleListener {
override val viewModel: ViewModel by viewModels()
private lateinit var navigatorAdapter: MainTabsAdapter
private val fragmentStateAdapter by lazy { MainViewPagerAdapter(this) }
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
fragmentStateAdapter.getFragmentByIndex(0).asSafe<OnSwitchTabListener>()
?.onSwitchTab(-1)
binding.viewPager2.setCurrentItem(0, false)
}
}
override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater)
override fun ViewBinding.initWindowInsets() {
ViewCompat.setOnApplyWindowInsetsListener(magicIndicator) { v, insets ->
val systemBars =
insets.getInsets(WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.displayCutout())
v.setPadding(
systemBars.left,
36,
systemBars.right,
systemBars.bottom + 36
)
insets
}
}
override fun ViewBinding.initViews() {
content.foreground.alpha = 0
navigatorAdapter = MainTabsAdapter(
this@MainActivity, viewPager2, fragmentStateAdapter, magicIndicator
)
magicIndicator.setCommonNavigator { isAdjustMode = true }
magicIndicator.bindViewPager2(viewPager2)
viewPager2.isUserInputEnabled = false
viewPager2.setPageTransformer { _, _ -> }
}
override fun ViewBinding.initListeners() {
onBackPressedDispatcher.addCallback(this@MainActivity, onBackPressedCallback)
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
setOnBackPressedCallbackIsEnabled()
}
})
supportFragmentManager.registerFragmentLifecycleCallbacks(object :
FragmentLifecycleCallbacks() {
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
super.onFragmentResumed(fm, f)
val isBackgroundBright =
f.asSafe<OnFragmentBackgroundListener>()?.isBackgroundBright
?: return
onTabIsDarkFont(isBackgroundBright)
}
}, false)
}
override fun ViewBinding.initObservers() {
}
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
magicIndicator.setDataOrAdapter(uiState.tabs) { navigatorAdapter }
viewPager2.setDataOrAdapter(uiState.tabs, Int.MAX_VALUE) { fragmentStateAdapter }
}
private fun setOnBackPressedCallbackIsEnabled() {
onBackPressedCallback.isEnabled = binding.viewPager2.currentItem != 0
}
override fun onResume() {
super.onResume()
}
override fun onTabIsDarkFont(isDarkFont: Boolean) {
navigatorAdapter.setIsDarkFont(isDarkFont)
}
}

View File

@ -0,0 +1,59 @@
package com.gamedog.vididin.main
import androidx.lifecycle.viewModelScope
import com.ama.core.architecture.appBase.vm.AppViewModel
import com.gamedog.vididin.R
import com.gamedog.vididin.beans.MainTabsItem
import com.gamedog.vididin.repository.MainRepository
import com.gamedog.vididin.repository.MainTabType
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import javax.inject.Inject
import com.gamedog.vididin.main.MainUiState as UiState
@HiltViewModel
class MainViewModel @Inject constructor(
mainRepository: MainRepository,
) : AppViewModel<UiState>() {
override val uiStateInitialValue: UiState = UiState()
override val uiStateFlow: Flow<UiState> = mainRepository.getMainTabsStream().map {
it.map { type ->
val title = when (type) {
MainTabType.HOME -> R.string.main_tabs_home
MainTabType.TASKS -> R.string.main_tabs_tasks
MainTabType.MINE -> R.string.main_tabs_mine
}
val normalIcon = when (type) {
MainTabType.HOME -> R.mipmap.tab_home
MainTabType.TASKS -> R.mipmap.tab_tasks
MainTabType.MINE -> R.mipmap.tab_my
}
val selectedIcon = when (type) {
MainTabType.HOME -> R.mipmap.tab_home_selected
MainTabType.TASKS -> R.mipmap.tab_tasks_selected
MainTabType.MINE -> R.mipmap.tab_my_selected
}
MainTabsItem(title, type, normalIcon, selectedIcon) {
viewModelScope.launch {
// TODO any other action you need
}
}
}
}.map {
UiState(tabs = it)
}
}
data class MainUiState(
val tabs: List<MainTabsItem>? = null,
)

View File

@ -0,0 +1,125 @@
package com.gamedog.vididin.main.fragments
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
import androidx.fragment.app.viewModels
import androidx.viewpager2.widget.ViewPager2
import com.ama.core.architecture.appBase.AppViewsFragment
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
import com.ama.core.architecture.util.setDataOrAdapter
import com.ama.core.common.util.asSafe
import com.gamedog.vididin.main.fragments.home.HomeFragmentStateAdapter
import com.gamedog.vididin.main.interfaces.OnSwitchTabListener
import com.gamedog.vididin.main.interfaces.OnTabStyleListener
import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue
import com.gamedog.vididin.databinding.VididinappFeatureHomeFragmentHomeBinding as ViewBinding
import com.gamedog.vididin.main.fragments.home.YoutubeViewModel as ViewModel
import com.gamedog.vididin.main.fragments.home.YoutubeUiState as UiState
@AndroidEntryPoint
class HomeFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(), OnSwitchTabListener,
OnFragmentBackgroundListener {
override val viewModel: ViewModel by viewModels()
override var isBackgroundBright: Boolean = true
private val onBackPressedCallback = object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() {
}
}
private val mViewPagerAdapter by lazy { HomeFragmentStateAdapter(this) }
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
) = ViewBinding.inflate(inflater, container, false)
override fun ViewBinding.initWindowInsets() {
ViewCompat.setOnApplyWindowInsetsListener(viewPager2) { v, insets ->
val systemBars =
insets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
v.updatePadding(top = systemBars.top)
insets
}
}
override fun ViewBinding.initViews() {
viewPager2.setPageTransformer { _, _ -> }
viewPager2.offscreenPageLimit = 1
}
override fun ViewBinding.initListeners() {
requireActivity().onBackPressedDispatcher.addCallback(
this@HomeFragment,
onBackPressedCallback
)
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
setHomeTabStyle(mViewPagerAdapter.getFragmentByIndex(position))
setOnBackPressedCallbackIsEnabled()
}
})
childFragmentManager.registerFragmentLifecycleCallbacks(object :
FragmentLifecycleCallbacks() {
override fun onFragmentResumed(fm: FragmentManager, f: Fragment) {
super.onFragmentResumed(fm, f)
setHomeTabStyle(f)
}
}, false)
}
override fun ViewBinding.initObservers() {
}
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
viewPager2.setDataOrAdapter(uiState.playLists, 1) { mViewPagerAdapter }
}
override fun onResume() {
super.onResume()
setOnBackPressedCallbackIsEnabled()
}
override fun onPause() {
super.onPause()
setOnBackPressedCallbackIsEnabled()
}
override fun onSwitchTab(index: Int, smoothScroll: Boolean) {
var item = index
if (index < 0 || index >= mViewPagerAdapter.itemCount) {
item = mViewPagerAdapter.itemCount - 1
}
binding?.viewPager2?.setCurrentItem(item, smoothScroll)
}
private fun setOnBackPressedCallbackIsEnabled() {
onBackPressedCallback.isEnabled =
isResumed && binding?.viewPager2?.currentItem != mViewPagerAdapter.itemCount - 1
}
private fun setHomeTabStyle(f: Fragment?) {
isBackgroundBright = f.asSafe<OnFragmentBackgroundListener>()?.isBackgroundBright ?: return
activity.asSafe<OnTabStyleListener>()?.onTabIsDarkFont(isBackgroundBright)
}
companion object {
internal fun newInstance() = HomeFragment()
}
}

View File

@ -0,0 +1,61 @@
package com.gamedog.vididin.main.fragments
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.ama.core.architecture.appBase.AppViewsFragment
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
import com.ama.core.architecture.util.setStatusBarDarkFont
import dagger.hilt.android.AndroidEntryPoint
import kotlin.getValue
import com.gamedog.vididin.databinding.VididinappFeatureMineFragmentMineBinding as ViewBinding
import com.gamedog.vididin.main.fragments.mine.MineUiState as UiState
import com.gamedog.vididin.main.fragments.mine.MineViewModel as ViewModel
@AndroidEntryPoint
class MineFragment : AppViewsFragment<ViewBinding, UiState, ViewModel>(),
OnFragmentBackgroundListener {
override val viewModel: ViewModel by viewModels()
override var isBackgroundBright: Boolean = true
private var isStatusBarDarkFont = false
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
) = ViewBinding.inflate(inflater, container, false)
override fun ViewBinding.initViews() {
}
override fun ViewBinding.initListeners() {
nestedScrollView.setOnScrollChangeListener { _, _, scrollY, _, _ ->
isStatusBarDarkFont = scrollY > topBackground.height
setStatusBarDarkFont(isStatusBarDarkFont)
}
}
override fun ViewBinding.initObservers() {
}
override fun ViewBinding.onUiStateCollect(uiState: UiState) {
//dynamicColorsSwitch.isChecked = uiState.useDynamicColor
}
override fun onResume() {
super.onResume()
setStatusBarDarkFont(isDarkFont = isStatusBarDarkFont)
}
companion object {
internal fun newInstance() = MineFragment()
}
}

View File

@ -0,0 +1,47 @@
package com.gamedog.vididin.main.fragments
import android.view.LayoutInflater
import android.view.ViewGroup
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelFragment
import com.ama.core.architecture.appBase.OnFragmentBackgroundListener
import com.ama.core.architecture.util.setStatusBarDarkFont
import com.gamedog.vididin.databinding.VididinappFeatureMessageFragmentMessageBinding as ViewBinding
import com.gamedog.vididin.main.interfaces.OnTabClickAgainListener
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class TasksFragment : AppViewsEmptyViewModelFragment<ViewBinding>(), OnTabClickAgainListener,
OnFragmentBackgroundListener {
override var isBackgroundBright: Boolean = true
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
) = ViewBinding.inflate(inflater, container, false)
override fun ViewBinding.initViews() {
}
override fun ViewBinding.initListeners() {
}
override fun ViewBinding.initObservers() {
}
override fun onResume() {
super.onResume()
setStatusBarDarkFont(isDarkFont = isBackgroundBright)
}
override fun onTabClickAgain() {
}
companion object {
internal fun newInstance() = TasksFragment()
}
}

View File

@ -0,0 +1,22 @@
package com.gamedog.vididin.feature.home.repository
import com.gamedog.vididin.feature.home.api.YoutubeApi
import com.gamedog.vididin.main.fragments.home.YoutubeDataSource
import retrofit2.Retrofit
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class DefaultYoutubeDatasource @Inject constructor(retrofit: Retrofit) : YoutubeDataSource {
private val shopApi = retrofit.create(YoutubeApi::class.java)
override suspend fun getChannels(
) = shopApi.getChannelList()
override suspend fun getPlayList(
) = shopApi.getVideoList()
}

View File

@ -0,0 +1,39 @@
package com.gamedog.vididin.feature.home.repository
import com.gamedog.vididin.beans.ResYoutubeChannel
import com.gamedog.vididin.beans.ResYoutubePlayList
import com.gamedog.vididin.beans.YoutubeVideo
import com.gamedog.vididin.core.data.repository.refreshloadmore.PageKeyedMemoryRefreshLoadMoreRepository
import com.gamedog.vididin.main.fragments.home.YoutubeDataSource
import com.gamedog.vididin.main.fragments.home.YoutubeRepository
import javax.inject.Inject
class DefaultYoutubeRepository @Inject constructor(
private val network: YoutubeDataSource,
) : PageKeyedMemoryRefreshLoadMoreRepository<YoutubeVideo>(), YoutubeRepository {
override suspend fun getVideoList(
page: Int,
size: Int
): ResYoutubePlayList {
return network.getPlayList()
}
override suspend fun getChannelList(
page: Int,
size: Int
): ResYoutubeChannel {
return network.getChannels()
}
override suspend fun getListDataByKey(
key: Int,
pageSize: Int
): List<YoutubeVideo>? {
return getVideoList(key, pageSize).items
}
}

View File

@ -0,0 +1,16 @@
package com.gamedog.vididin.main.fragments.home
import androidx.fragment.app.Fragment
import com.ama.core.architecture.appBase.adapter.AppFragmentStateAdapter
import com.gamedog.vididin.beans.YoutubeVideo
import com.gamedog.vididin.main.fragments.home.fragment.HomeItemFragment
class HomeFragmentStateAdapter(fragment: Fragment) :
AppFragmentStateAdapter<YoutubeVideo>(fragment, true) {
override fun createFragment(position: Int, item: YoutubeVideo): Fragment {
return HomeItemFragment.newInstance(item.getItemId(), item)
}
}

View File

@ -0,0 +1,14 @@
package com.gamedog.vididin.main.fragments.home
interface OnRepositoryRefreshListener {
fun refresh(finish: (() -> Unit)? = null)
}
interface OnRepositoryLoadMoreListener {
fun load()
fun loadRetry()
}

View File

@ -0,0 +1,8 @@
package com.gamedog.vididin.main.fragments.home
import com.ama.core.architecture.page.RefreshRepository
interface RefreshRepositoryOwner {
fun onRefreshRepository(): RefreshRepository<*>
}

View File

@ -0,0 +1,10 @@
package com.gamedog.vididin.main.fragments.home
import com.gamedog.vididin.beans.ResYoutubeChannel
import com.gamedog.vididin.beans.ResYoutubePlayList
interface YoutubeDataSource {
suspend fun getChannels(): ResYoutubeChannel
suspend fun getPlayList(): ResYoutubePlayList
}

View File

@ -0,0 +1,12 @@
package com.gamedog.vididin.main.fragments.home
import com.ama.core.architecture.page.RefreshLoadMoreRepository
import com.gamedog.vididin.beans.ResYoutubeChannel
import com.gamedog.vididin.beans.ResYoutubePlayList
import com.gamedog.vididin.beans.YoutubeVideo
interface YoutubeRepository : RefreshLoadMoreRepository<YoutubeVideo> {
suspend fun getVideoList(page: Int, size: Int): ResYoutubePlayList
suspend fun getChannelList(page: Int, size: Int): ResYoutubeChannel
}

View File

@ -0,0 +1,32 @@
package com.gamedog.vididin.main.fragments.home
import com.ama.core.architecture.appBase.vm.AppViewModel
import com.ama.core.architecture.page.RefreshRepository
import com.gamedog.vididin.beans.YoutubeVideo
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
@HiltViewModel
class YoutubeViewModel @Inject constructor(
private val mRepository: YoutubeRepository,
) : AppViewModel<YoutubeUiState>(), RefreshRepositoryOwner {
override val uiStateInitialValue: YoutubeUiState = YoutubeUiState()
override val uiStateFlow: Flow<YoutubeUiState> = mRepository.result.map { listData ->
YoutubeUiState(playLists = listData)
}
override fun onRefreshRepository(): RefreshRepository<*> {
TODO("Not yet implemented")
}
}
data class YoutubeUiState(
val playLists: List<YoutubeVideo>? = null,
)

View File

@ -0,0 +1,216 @@
package com.gamedog.vididin.main.fragments.home.fragment
import android.os.Bundle
import android.provider.MediaStore.Audio.Playlists.Members.PLAYLIST_ID
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.annotation.NonNull
import com.ama.core.architecture.appBase.AppViewsEmptyViewModelFragment
import com.ama.core.common.widget.PopMenuIconView
import com.gamedog.vididin.R
import com.gamedog.vididin.beans.YoutubeVideo
import com.gamedog.vididin.widget.MyPlayerControlView
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.PlayerConstants
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.YouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.options.IFramePlayerOptions
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
import kotlin.apply
import kotlin.toString
import com.gamedog.vididin.databinding.VididinappFeatureHomeItemLayoutBinding as ViewBinding
class HomeItemFragment : AppViewsEmptyViewModelFragment<ViewBinding>() {
private var mIsStared = false
private var mPlayer: YouTubePlayer? = null
private var mVideoData: YoutubeVideo? = null
override fun inflateViewBinding(
inflater: LayoutInflater,
container: ViewGroup?,
) = ViewBinding.inflate(inflater, container, false)
override fun ViewBinding.initViews() {
tvPlay.setOnClickListener {
mPlayer?.play()
}
tvPause.setOnClickListener {
mPlayer?.pause()
//mPlayer.seekTo()
mPlayer?.setPlaybackRate(PlayerConstants.PlaybackRate.RATE_2)
}
tvVideoFrom.text = "@From-" + arguments?.getLong(KEY_ID).toString()
tvVideoIntro.text = "Introduce-" + arguments?.getLong(KEY_ID).toString()
popMenu.setMenuList(
mutableListOf(
PopMenuIconView.MenuItem(R.mipmap.home_menu_1) {
},
PopMenuIconView.MenuItem(R.mipmap.home_menu_2) {
},
PopMenuIconView.MenuItem(R.mipmap.home_menu_3) {
},
PopMenuIconView.MenuItem(R.mipmap.home_menu_4) {
}
))
lifecycle.addObserver(youtubePlayerView)
youtubePlayerView.enableBackgroundPlayback(false)
youtubePlayerView.enableAutomaticInitialization = false
}
fun initAndStartPlay() {
val youtubePlayerView: YouTubePlayerView = binding?.youtubePlayerView!!
val iFramePlayerOptions = IFramePlayerOptions.Builder(requireContext())
.rel(1)
.ccLoadPolicy(1)
.controls(0)
.listType("playlist")
.list(PLAYLIST_ID)
.fullscreen(0)
.build()
youtubePlayerView.initialize(object : YouTubePlayerListener {
override fun onReady(youTubePlayer: YouTubePlayer) {
}
override fun onStateChange(
youTubePlayer: YouTubePlayer,
state: PlayerConstants.PlayerState
) {
}
override fun onPlaybackQualityChange(
youTubePlayer: YouTubePlayer,
playbackQuality: PlayerConstants.PlaybackQuality
) {
}
override fun onPlaybackRateChange(
youTubePlayer: YouTubePlayer,
playbackRate: PlayerConstants.PlaybackRate
) {
}
override fun onError(
youTubePlayer: YouTubePlayer,
error: PlayerConstants.PlayerError
) {
}
override fun onCurrentSecond(
youTubePlayer: YouTubePlayer,
second: Float
) {
}
override fun onVideoDuration(
youTubePlayer: YouTubePlayer,
duration: Float
) {
}
override fun onVideoLoadedFraction(
youTubePlayer: YouTubePlayer,
loadedFraction: Float
) {
}
override fun onVideoId(
youTubePlayer: YouTubePlayer,
videoId: String
) {
}
override fun onApiChange(youTubePlayer: YouTubePlayer) {
}
}, iFramePlayerOptions)
youtubePlayerView.addYouTubePlayerListener(object : AbstractYouTubePlayerListener() {
override fun onReady(@NonNull youTubePlayer: YouTubePlayer) {
mPlayer = youTubePlayer
//val playerUiController = DefaultPlayerUiController(youtubePlayerView, youTubePlayer)
val playerUiController = MyPlayerControlView(youtubePlayerView, youTubePlayer)
youtubePlayerView.setCustomPlayerUi(playerUiController.rootView)
if (mVideoData != null && !mVideoData?.id.isNullOrEmpty()) {
youTubePlayer.loadVideo(mVideoData!!.id, 0f)
}
}
override fun onStateChange(
youTubePlayer: YouTubePlayer,
state: PlayerConstants.PlayerState
) {
when (state) {
PlayerConstants.PlayerState.UNKNOWN -> { }
PlayerConstants.PlayerState.UNSTARTED -> { }
PlayerConstants.PlayerState.ENDED -> { }
PlayerConstants.PlayerState.PLAYING -> { }
PlayerConstants.PlayerState.PAUSED -> { }
PlayerConstants.PlayerState.BUFFERING -> { }
PlayerConstants.PlayerState.VIDEO_CUED -> { }
}
}
})
}
override fun ViewBinding.initListeners() {
ivStar.setOnClickListener {
mIsStared = !mIsStared
ivStar.setImageResource(if (mIsStared) R.mipmap.home_star else R.mipmap.home_star_undo)
}
}
override fun ViewBinding.initObservers() {
try {
initAndStartPlay()
} catch (e: Exception) {
e.printStackTrace()
}
}
companion object {
private const val KEY_ID = "id"
internal fun newInstance(id: Long, videoData: YoutubeVideo) = HomeItemFragment().apply {
mVideoData = videoData
arguments = Bundle().apply {
putLong(KEY_ID, id)
}
}
}
}

View File

@ -0,0 +1,33 @@
package com.gamedog.vididin.main.fragments.mine
import androidx.lifecycle.viewModelScope
import com.ama.core.architecture.appBase.vm.AppViewModel
import com.gamedog.vididin.core.datastore.AppPreferencesDataSource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
import javax.inject.Inject
import com.gamedog.vididin.main.fragments.mine.MineUiState as UiState
@HiltViewModel
class MineViewModel @Inject constructor(
private val preferencesDataSource: AppPreferencesDataSource,
) : AppViewModel<UiState>() {
override val uiStateInitialValue: UiState = UiState()
override val uiStateFlow: Flow<UiState> = flowOf()
fun updateDynamicColorPreference(useDynamicColor: Boolean, finish: () -> Unit) {
if (useDynamicColor == uiState.value.useDynamicColor) return
viewModelScope.launch {
delay(250)
finish()
}
}
}
data class MineUiState(
val useDynamicColor: Boolean = false,
)

View File

@ -0,0 +1,6 @@
package com.gamedog.vididin.main.interfaces
interface OnSwitchTabListener {
fun onSwitchTab(index: Int, smoothScroll: Boolean = false)
}

View File

@ -0,0 +1,17 @@
package com.gamedog.vididin.main.interfaces
interface OnTabClickRefreshListener {
fun onTabClickRefresh(listener: OnTabClickRefreshFinishListener)
}
interface OnTabClickRefreshFinishListener {
fun onTabClickRefreshFinish()
}
@Suppress("EmptyMethod")
interface OnTabClickAgainListener {
fun onTabClickAgain()
}

View File

@ -0,0 +1,6 @@
package com.gamedog.vididin.main.interfaces
interface OnTabStyleListener {
fun onTabIsDarkFont(isDarkFont: Boolean)
}

View File

@ -0,0 +1,25 @@
package com.gamedog.vididin.repository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import javax.inject.Inject
class DefaultMainRepository @Inject constructor(
) : MainRepository {
override fun getMainTabsStream(): Flow<List<MainTabType>> {
return flowOf(listOf(MainTabType.HOME, MainTabType.TASKS, MainTabType.MINE))
}
private suspend fun setDefaultMainTabs() {
val arrayListOf = arrayListOf(
MainTabType.HOME,
MainTabType.TASKS,
MainTabType.MINE
)
}
}

View File

@ -0,0 +1,14 @@
package com.gamedog.vididin.repository
import kotlinx.coroutines.flow.Flow
interface MainRepository {
fun getMainTabsStream(): Flow<List<MainTabType>>
}
enum class MainTabType {
HOME,
TASKS,
MINE,
}

View File

@ -0,0 +1,10 @@
package com.gamedog.vididin.router
import androidx.fragment.app.Fragment
import com.gamedog.vididin.core.router.interfaces.HomeRouter
import com.gamedog.vididin.main.fragments.HomeFragment
class DefaultHomeRouter : HomeRouter {
override fun createHomeFragment(): Fragment = HomeFragment.newInstance()
}

View File

@ -0,0 +1,12 @@
package com.gamedog.vididin.router
import android.app.Activity
import com.gamedog.vididin.core.router.interfaces.LoginRouter
import com.gamedog.vididin.login.LoginActivity
class DefaultLoginRouter : LoginRouter {
override fun startLoginActivity(activity: Activity) {
LoginActivity.startActivity(activity)
}
}

View File

@ -0,0 +1,11 @@
package com.gamedog.vididin.router
import androidx.fragment.app.Fragment
import com.gamedog.vididin.core.router.interfaces.MineRouter
import com.gamedog.vididin.main.fragments.MineFragment
class DefaultMineRouter : MineRouter {
override fun createMineFragment(): Fragment = MineFragment.newInstance()
}

View File

@ -0,0 +1,11 @@
package com.gamedog.vididin.router
import androidx.fragment.app.Fragment
import com.gamedog.vididin.core.router.interfaces.TaskRouter
import com.gamedog.vididin.main.fragments.TasksFragment
class DefaultTaskRouter : TaskRouter {
override fun createTaskFragment(): Fragment = TasksFragment.newInstance()
}

View File

@ -0,0 +1,7 @@
package com.gamedog.vididin.core.router.interfaces
import androidx.fragment.app.Fragment
interface HomeRouter {
fun createHomeFragment(): Fragment
}

View File

@ -0,0 +1,7 @@
package com.gamedog.vididin.core.router.interfaces
import android.app.Activity
interface LoginRouter {
fun startLoginActivity(activity: Activity)
}

View File

@ -0,0 +1,7 @@
package com.gamedog.vididin.core.router.interfaces
import androidx.fragment.app.Fragment
interface MineRouter {
fun createMineFragment(): Fragment
}

View File

@ -0,0 +1,27 @@
package com.gamedog.vididin.router
import android.content.Context
import com.gamedog.vididin.core.router.interfaces.HomeRouter
import com.gamedog.vididin.core.router.interfaces.LoginRouter
import com.gamedog.vididin.core.router.interfaces.MineRouter
import com.gamedog.vididin.core.router.interfaces.TaskRouter
import com.gamedog.vididin.di.RouterEntryPoint
import dagger.hilt.android.EntryPointAccessors
import kotlin.getValue
import kotlin.jvm.java
object Router : RouterContract {
private lateinit var routerEntryPoint: RouterEntryPoint
fun init(context: Context) {
routerEntryPoint = EntryPointAccessors.fromApplication(context, RouterEntryPoint::class.java)
}
override val Home: HomeRouter by lazy { routerEntryPoint.homeRouter() }
override val Task: TaskRouter by lazy { routerEntryPoint.taskRouter() }
override val Mine: MineRouter by lazy { routerEntryPoint.mineRouter() }
override val Login: LoginRouter by lazy { routerEntryPoint.loginRouter() }
}

View File

@ -0,0 +1,15 @@
package com.gamedog.vididin.router
import com.gamedog.vididin.core.router.interfaces.HomeRouter
import com.gamedog.vididin.core.router.interfaces.LoginRouter
import com.gamedog.vididin.core.router.interfaces.TaskRouter
import com.gamedog.vididin.core.router.interfaces.MineRouter
@Suppress("PropertyName")
interface RouterContract {
val Home: HomeRouter
val Task: TaskRouter
val Mine: MineRouter
val Login: LoginRouter
}

View File

@ -0,0 +1,15 @@
package com.gamedog.vididin.router
import android.content.Context
import androidx.startup.Initializer
class RouterInitializer : Initializer<Unit> {
override fun create(context: Context) {
Router.init(context)
}
override fun dependencies(): MutableList<Class<out Initializer<*>>> {
return mutableListOf()
}
}

View File

@ -0,0 +1,8 @@
package com.gamedog.vididin.core.router.interfaces
import androidx.fragment.app.Fragment
interface TaskRouter {
fun createTaskFragment(): Fragment
}

View File

@ -0,0 +1,11 @@
package com.gamedog.vididin.core.datastore
import javax.inject.Inject
class AppPreferencesDataSource @Inject constructor(
) {
}

View File

@ -0,0 +1,10 @@
package com.gamedog.vididin.core.datastore
import javax.inject.Inject
class UserPreferencesSerializer @Inject constructor() {
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
option java_package = "com.gamedog.vididin.sp.datastore";
option java_multiple_files = true;
message User {
int32 id = 1;
string token = 2;
string account = 3;
string createdAt = 4;
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
import "com/gamedog/vididin/sp/datastore/user.proto";
option java_package = "com.gamedog.vididin.sp.datastore";
option java_multiple_files = true;
message UserPreferences {
// Useruser
User user = 1;
// List<Integer>Tabs
repeated int32 main_tabs = 2;
// List<Integer>Tabs
repeated int32 home_tabs = 3;
// booleanUseDynamicColor
bool use_dynamic_color = 4;
}

View File

@ -0,0 +1,30 @@
package com.gamedog.vididin.widget
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import com.gamedog.vididin.databinding.LayoutDragIconViewBinding
import kotlin.run
class HomeDragIconView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private var mBinding: LayoutDragIconViewBinding? = null
init {
mBinding = LayoutDragIconViewBinding.inflate(LayoutInflater.from(context), this, true)
mBinding?.run {
}
}
}

View File

@ -0,0 +1,294 @@
package com.gamedog.vididin.widget
import android.content.Intent
import android.graphics.drawable.Drawable
import android.net.Uri
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.gamedog.vididin.R
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.PlayerUiController
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.PlayerConstants
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.menu.YouTubePlayerMenu
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.utils.FadeViewHelper
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.views.YouTubePlayerSeekBar
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.views.YouTubePlayerSeekBarListener
import kotlin.jvm.javaClass
class MyPlayerControlView(
private val youTubePlayerView: YouTubePlayerView,
private val youTubePlayer: YouTubePlayer
) : PlayerUiController {
val rootView: View = View.inflate(youTubePlayerView.context, R.layout.layout_player_controller, null)
private var youTubePlayerMenu: YouTubePlayerMenu = MyPlayerMenu(
youTubePlayerView.context
)
/**
* View used for for intercepting clicks and for drawing a black background.
* Could have used controlsContainer, but in this way I'm able to hide all the control at once by hiding controlsContainer
*/
private val panel: View = rootView.findViewById(R.id.panel)
private val controlsContainer: View = rootView.findViewById(R.id.controls_container)
private val extraViewsContainer: LinearLayout = rootView.findViewById(R.id.extra_views_container)
private val videoTitle: TextView = rootView.findViewById(R.id.video_title)
private val liveVideoIndicator: TextView = rootView.findViewById(R.id.live_video_indicator)
private val progressBar: ProgressBar = rootView.findViewById(R.id.progress)
private val menuButton: ImageView = rootView.findViewById(R.id.menu_button)
private val playPauseButton: ImageView = rootView.findViewById(R.id.play_pause_button)
private val youTubeButton: ImageView = rootView.findViewById(R.id.youtube_button)
private val fullscreenButton: ImageView = rootView.findViewById(R.id.fullscreen_button)
private val customActionLeft: ImageView = rootView.findViewById(R.id.custom_action_left_button)
private val customActionRight: ImageView = rootView.findViewById(R.id.custom_action_right_button)
private val youtubePlayerSeekBar: YouTubePlayerSeekBar = rootView.findViewById(R.id.youtube_player_seekbar)
private val fadeControlsContainer: FadeViewHelper = FadeViewHelper(controlsContainer)
private var onFullscreenButtonListener: View.OnClickListener
private var onMenuButtonClickListener: View.OnClickListener
private var isPlaying = false
private var isPlayPauseButtonEnabled = true
private var isCustomActionLeftEnabled = false
private var isCustomActionRightEnabled = false
private var isMatchParent = false
private val youTubePlayerStateListener = object : AbstractYouTubePlayerListener() {
override fun onStateChange(youTubePlayer: YouTubePlayer, state: PlayerConstants.PlayerState) {
updateState(state)
if (state === PlayerConstants.PlayerState.PLAYING || state === PlayerConstants.PlayerState.PAUSED || state === PlayerConstants.PlayerState.VIDEO_CUED) {
panel.setBackgroundColor(ContextCompat.getColor(panel.context, R.color.transparent))
progressBar.visibility = View.GONE
if (isPlayPauseButtonEnabled) playPauseButton.visibility = View.VISIBLE
if (isCustomActionLeftEnabled) customActionLeft.visibility = View.VISIBLE
if (isCustomActionRightEnabled) customActionRight.visibility = View.VISIBLE
updatePlayPauseButtonIcon(state === PlayerConstants.PlayerState.PLAYING)
} else {
updatePlayPauseButtonIcon(false)
if (state === PlayerConstants.PlayerState.BUFFERING) {
progressBar.visibility = View.VISIBLE
panel.setBackgroundColor(
ContextCompat.getColor(
panel.context,
R.color.transparent
)
)
if (isPlayPauseButtonEnabled) playPauseButton.visibility = View.INVISIBLE
customActionLeft.visibility = View.GONE
customActionRight.visibility = View.GONE
}
if (state === PlayerConstants.PlayerState.UNSTARTED) {
progressBar.visibility = View.GONE
if (isPlayPauseButtonEnabled) playPauseButton.visibility = View.VISIBLE
}
}
}
override fun onVideoId(youTubePlayer: YouTubePlayer, videoId: String) {
youTubeButton.setOnClickListener {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://www.youtube.com/watch?v=" + videoId + "#t=" + youtubePlayerSeekBar.seekBar.progress)
)
try {
youTubeButton.context.startActivity(intent)
} catch (e: Exception) {
Log.e(javaClass.simpleName, e.message ?: "Can't open url to YouTube")
}
}
}
}
init {
onFullscreenButtonListener = View.OnClickListener {
isMatchParent = !isMatchParent
when (isMatchParent) {
true -> youTubePlayerView.matchParent()
false -> youTubePlayerView.wrapContent()
}
}
onMenuButtonClickListener = View.OnClickListener { youTubePlayerMenu.show(menuButton) }
initClickListeners()
}
private fun initClickListeners() {
youTubePlayer.addListener(youtubePlayerSeekBar)
youTubePlayer.addListener(fadeControlsContainer)
youTubePlayer.addListener(youTubePlayerStateListener)
youtubePlayerSeekBar.youtubePlayerSeekBarListener = object : YouTubePlayerSeekBarListener {
override fun seekTo(time: Float) = youTubePlayer.seekTo(time)
}
panel.setOnClickListener { fadeControlsContainer.toggleVisibility() }
playPauseButton.setOnClickListener { onPlayButtonPressed() }
fullscreenButton.setOnClickListener { onFullscreenButtonListener.onClick(fullscreenButton) }
menuButton.setOnClickListener { onMenuButtonClickListener.onClick(menuButton) }
}
override fun showVideoTitle(show: Boolean): PlayerUiController {
videoTitle.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun setVideoTitle(videoTitle: String): PlayerUiController {
this.videoTitle.text = videoTitle
return this
}
override fun showUi(show: Boolean): PlayerUiController {
fadeControlsContainer.isDisabled = !show
controlsContainer.visibility = if (show) View.VISIBLE else View.INVISIBLE
return this
}
override fun showPlayPauseButton(show: Boolean): PlayerUiController {
playPauseButton.visibility = if (show) View.VISIBLE else View.GONE
isPlayPauseButtonEnabled = show
return this
}
override fun enableLiveVideoUi(enable: Boolean): PlayerUiController {
youtubePlayerSeekBar.visibility = if (enable) View.INVISIBLE else View.VISIBLE
liveVideoIndicator.visibility = if (enable) View.VISIBLE else View.GONE
return this
}
override fun setCustomAction1(
icon: Drawable,
clickListener: View.OnClickListener?
): PlayerUiController {
customActionLeft.setImageDrawable(icon)
customActionLeft.setOnClickListener(clickListener)
showCustomAction1(true)
return this
}
override fun setCustomAction2(
icon: Drawable,
clickListener: View.OnClickListener?
): PlayerUiController {
customActionRight.setImageDrawable(icon)
customActionRight.setOnClickListener(clickListener)
showCustomAction2(true)
return this
}
override fun showCustomAction1(show: Boolean): PlayerUiController {
isCustomActionLeftEnabled = show
customActionLeft.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun showCustomAction2(show: Boolean): PlayerUiController {
isCustomActionRightEnabled = show
customActionRight.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun showMenuButton(show: Boolean): PlayerUiController {
menuButton.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun setMenuButtonClickListener(customMenuButtonClickListener: View.OnClickListener): PlayerUiController {
onMenuButtonClickListener = customMenuButtonClickListener
return this
}
override fun showCurrentTime(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.videoCurrentTimeTextView.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun showDuration(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.videoDurationTextView.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun showSeekBar(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.seekBar.visibility = if (show) View.VISIBLE else View.INVISIBLE
return this
}
override fun showBufferingProgress(show: Boolean): PlayerUiController {
youtubePlayerSeekBar.showBufferingProgress = show
return this
}
override fun showYouTubeButton(show: Boolean): PlayerUiController {
youTubeButton.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun addView(view: View): PlayerUiController {
extraViewsContainer.addView(view, 0)
return this
}
override fun removeView(view: View): PlayerUiController {
extraViewsContainer.removeView(view)
return this
}
override fun getMenu(): YouTubePlayerMenu = youTubePlayerMenu
override fun showFullscreenButton(show: Boolean): PlayerUiController {
fullscreenButton.visibility = if (show) View.VISIBLE else View.GONE
return this
}
override fun setFullscreenButtonClickListener(customFullscreenButtonClickListener: View.OnClickListener): PlayerUiController {
onFullscreenButtonListener = customFullscreenButtonClickListener
return this
}
private fun onPlayButtonPressed() {
if (isPlaying)
youTubePlayer.pause()
else
youTubePlayer.play()
}
private fun updateState(state: PlayerConstants.PlayerState) {
when (state) {
PlayerConstants.PlayerState.ENDED -> isPlaying = false
PlayerConstants.PlayerState.PAUSED -> isPlaying = false
PlayerConstants.PlayerState.PLAYING -> isPlaying = true
else -> {}
}
updatePlayPauseButtonIcon(!isPlaying)
}
private fun updatePlayPauseButtonIcon(playing: Boolean) {
/*val drawable = if (playing) R.drawable.ayp_ic_pause_36dp else R.drawable.ayp_ic_play_36dp
playPauseButton.setImageResource(drawable)*/
}
}

View File

@ -0,0 +1,67 @@
package com.gamedog.vididin.widget
import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.PopupWindow
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.R
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.menu.MenuItem
import com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.menu.YouTubePlayerMenu
import kotlin.jvm.java
internal class MyPlayerMenu(private val context: Context) : YouTubePlayerMenu {
private val menuItems = kotlin.collections.ArrayList<MenuItem>()
private var popupWindow: PopupWindow? = null
override val itemCount: Int
get() = menuItems.size
override fun show(anchorView: View) {
popupWindow = createPopupWindow()
popupWindow?.showAsDropDown(
anchorView,
-context.resources.getDimensionPixelSize(R.dimen.ayp_8dp) * 12,
-context.resources.getDimensionPixelSize(R.dimen.ayp_8dp) * 12
)
if (menuItems.size == 0)
Log.e(YouTubePlayerMenu::class.java.name, "The menu is empty")
}
override fun dismiss() {
popupWindow?.dismiss()
}
override fun addItem(menuItem: MenuItem): YouTubePlayerMenu {
menuItems.add(menuItem)
return this
}
override fun removeItem(itemIndex: Int): YouTubePlayerMenu {
menuItems.removeAt(itemIndex)
return this
}
override fun removeItem(menuItem: MenuItem): YouTubePlayerMenu {
menuItems.remove(menuItem)
return this
}
private fun createPopupWindow(): PopupWindow {
val view = FrameLayout(context)
val popupWindow = PopupWindow(
view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
)
popupWindow.contentView = view
popupWindow.isFocusable = true
popupWindow.width = WindowManager.LayoutParams.WRAP_CONTENT
popupWindow.height = WindowManager.LayoutParams.WRAP_CONTENT
return popupWindow
}
}

View File

@ -0,0 +1,125 @@
package com.gamedog.vididin.widget;
public class YTParams {
/**
* 0或1默认值为0用于设置初始视频是否在加载播放器时自动播放
*/
private int autoplay = 0;
/**
* 2默认值1和0此参数会指明视频控件是否会在视频开始播放之后自动隐藏默认行为(autohide=2)表示当播放器控件播放按钮和音量控件等处于可见状态时视频进度条将淡出
如果将此参数设为1则视频进度条和播放器控件将会在视频开始播放几秒钟后退出播放界面仅在用户将鼠标移动到视频播放器上方或按键盘上的某个键时进度条和控件才会重新显示
如果将此参数设为0则视频进度条和视频播放器控件在视频播放全程和全屏状态下均会显示
*/
private int autohide = 1;
/**
* 0或1默认值为1此参数将表明初始视频播放结束时播放器是否应显示相关视频
*/
private int rel = 0;
/**
* 0或1此参数的默认值为1如果您将此参数的值设为0则在视频开始播放之前播放器不会显示视频标题和上传者等信息
*/
private int showinfo = 1;
/**
* 0或1默认值为0将此值设为1将会停用Javascript API.
*/
private int enablejsapi = 0;
/**
* 0或1默认值为0将此值设为1将会停用播放器键盘控件键盘控件如下
空格键播放/暂停
向左箭头当前视频后退10%
向右箭头当前视频前进10%
向上箭头调高音量
向下箭头降低音量
*/
private int disablekb = 1;
/**
* 01或2默认值为1此参数会指明视频播放器控件是否会显示对于加载Flash播放器的iframe嵌入
* 此参数还会定义控件何时在播放器中显示以及播放器加载时间
controls=0 - 播放器控件不会在播放器中显示对于iframe嵌入Flash播放器会立即加载
controls=1 - 播放器控件会在播放器中显示对于iframe嵌入控件会立即显示而且Flash播放器也会立即加载
controls=2 - 播放器控件会在播放器中显示对于iframe嵌入控件会显示而且Flash播放器会在用户启动视频播放时加载
注意参数值1和2用于提供一致的用户体验但是对于iframe嵌入而言controls=2提供的性能较之controls=1已得到改进
目前这两个参数值仍会在播放器中产生一些视觉方面的差异例如视频标题的字体大小
但是当两个参数值之间的差异对用户而言变得完全透明时默认参数值可能会从1更改为2
*/
private int controls = 1;
/**
* 0或1默认值为1该值会使全屏按钮显示将此参数设为0会阻止全屏按钮显示
*/
private int fs = 1;
private String cc_lang_pref = "en";
public int getFs() {
return fs;
}
public void setFs(int fs) {
this.fs = fs;
}
public int getAutoplay() {
return autoplay;
}
public void setAutoplay(int autoplay) {
this.autoplay = autoplay;
}
public int getAutohide() {
return autohide;
}
public void setAutohide(int autohide) {
this.autohide = autohide;
}
public int getRel() {
return rel;
}
public void setRel(int rel) {
this.rel = rel;
}
public int getShowinfo() {
return showinfo;
}
public void setShowinfo(int showinfo) {
this.showinfo = showinfo;
}
public int getEnablejsapi() {
return enablejsapi;
}
public void setEnablejsapi(int enablejsapi) {
this.enablejsapi = enablejsapi;
}
public int getDisablekb() {
return disablekb;
}
public void setDisablekb(int disablekb) {
this.disablekb = disablekb;
}
public String getCc_lang_pref() {
return cc_lang_pref;
}
public void setCc_lang_pref(String cc_lang_pref) {
this.cc_lang_pref = cc_lang_pref;
}
public int getControls() {
return controls;
}
public void setControls(int controls) {
this.controls = controls;
}
}

View File

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

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 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffff0a58"
android:endColor="#FFFF0AAF" android:angle="90" />
<corners android:topLeftRadius="45dp" android:topRightRadius="45dp"
android:bottomLeftRadius="45dp" android:bottomRightRadius="45dp" />
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#fff8bbc8"
android:endColor="#ffffffff" android:angle="90" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp"
android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffb4ffcd" android:endColor="#ffffffff" android:angle="90" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp" android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffffceae" android:endColor="#ffffffff" android:angle="90" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp" android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffff2a2a"
android:endColor="#ffff862f" android:angle="90" />
<corners android:topLeftRadius="45dp" android:topRightRadius="45dp"
android:bottomLeftRadius="45dp" android:bottomRightRadius="45dp" />
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffffff"
android:endColor="#fffff3d8" android:angle="90" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp"
android:bottomLeftRadius="15dp" android:bottomRightRadius="15dp" />
</shape>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true" android:startColor="#ffffffff"
android:endColor="#ffffffff" android:angle="90" />
<corners android:topLeftRadius="15dp" android:topRightRadius="15dp"
android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="linear" android:useLevel="true"
android:startColor="#00009b39" android:endColor="#99009b39" android:angle="90" />
</shape>

View File

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

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="@color/main_content_foreground">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/magic_indicator"
app:layout_constraintTop_toTopOf="parent" />
<net.lucode.hackware.magicindicator.MagicIndicator
android:id="@+id/magic_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="30dp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -0,0 +1,24 @@
<?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="wrap_content">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
tools:ignore="ContentDescription" />
<Button
android:id="@+id/title"
style="@style/design_text_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingVertical="@dimen/main_tab_item_padding_vertical"
android:textSize="@dimen/main_tab_item_title_test_size"
android:textStyle="bold" />
</FrameLayout>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<com.ama.core.common.widget.DragLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingVertical="7dp"
tools:ignore="ResourceName">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_menu_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/home_gold"
android:layout_gravity="center"
android:paddingVertical="7dp"
android:layout_marginTop="2dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/yellow_46"
android:text="+28"
android:layout_marginLeft="5dp"
/>
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/home_envelope"
android:layout_gravity="center"
android:paddingVertical="7dp"
/>
</FrameLayout>
</LinearLayout>
</com.ama.core.common.widget.DragLayout>

View File

@ -0,0 +1,204 @@
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="ResourceName">
<View
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:background="@android:color/black" />
<RelativeLayout
android:id="@+id/controls_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent" >
<View
android:id="@+id/drop_shadow_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:background="@drawable/ayp_drop_shadow_top" />
<View
android:id="@+id/drop_shadow_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:background="@drawable/ayp_drop_shadow_bottom" />
<TextView
android:id="@+id/video_title"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text=""
android:ellipsize="end"
android:textColor="@android:color/white"
android:textSize="14sp"
android:lines="1"
android:padding="8dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/extra_views_container" />
<LinearLayout
android:id="@+id/extra_views_container"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:orientation="horizontal"
android:padding="8dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" >
<ImageView
android:id="@+id/menu_button"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="0dp"
android:src="@drawable/ayp_ic_menu_24dp"
android:visibility="gone"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:contentDescription="@string/ayp_open_video_in_youtube" />
</LinearLayout>
<ImageView
android:id="@+id/play_pause_button"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ayp_ic_play_36dp"
android:visibility="invisible"
android:padding="8dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:layout_centerInParent="true"
android:contentDescription="@string/ayp_play_button" />
<ProgressBar
android:id="@+id/progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true" >
<com.pierfrancescosoffritti.androidyoutubeplayer.core.customui.views.YouTubePlayerSeekBar
android:id="@+id/youtube_player_seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:fontSize="12sp"
app:color="@color/ayp_red"
android:maxHeight="100dp" />
<TextView
android:id="@+id/live_video_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ayp_live"
android:textColor="@android:color/white"
android:textSize="12sp"
android:padding="8dp"
android:gravity="center_vertical"
android:visibility="gone" />
<ImageView
android:id="@+id/youtube_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ayp_ic_youtube_24dp"
android:padding="8dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:contentDescription="@string/ayp_open_video_in_youtube" />
<ImageView
android:id="@+id/fullscreen_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ayp_ic_fullscreen_24dp"
android:padding="8dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:contentDescription="@string/ayp_full_screen_button" />
</LinearLayout>
<ImageView
android:id="@+id/custom_action_left_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ayp_ic_play_36dp"
android:visibility="gone"
android:padding="8dp"
android:layout_margin="32dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:contentDescription="@string/ayp_custom_action_left"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/play_pause_button" />
<ImageView
android:id="@+id/custom_action_right_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ayp_ic_play_36dp"
android:visibility="gone"
android:padding="8dp"
android:layout_margin="32dp"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ayp_background_item_selected"
android:contentDescription="@string/ayp_custom_action_right"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/play_pause_button" />
</RelativeLayout>
</FrameLayout>

View File

@ -0,0 +1,20 @@
<?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" >
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
<com.gamedog.vididin.widget.HomeDragIconView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginLeft="20dp"
/>
</FrameLayout>

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!--<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/temp_bg"
android:scaleType="centerCrop"
/>-->
<!--<com.gamedog.vididin.feature.home.ui.widget.YoutubeWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />-->
<!--<com.gamedog.vididin.feature.home.ui.widget.YoutubePlayerView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>-->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:clickable="true"
/>
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="@+id/youtube_player_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<View
android:id="@+id/mask_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#33FF0000"
android:clickable="true"
/>
<LinearLayout
android:id="@+id/controls_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginHorizontal="15dp"
android:layout_marginBottom="100dp"
android:layout_gravity="bottom">
<TextView
android:id="@+id/tv_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#666666"
android:textColor="@color/white"
android:text="Play"
/>
<TextView
android:id="@+id/tv_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#666666"
android:textColor="@color/white"
android:text="pause"
android:layout_marginLeft="20dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginVertical="25dp"
android:layout_marginHorizontal="15dp"
android:layout_gravity="bottom">
<TextView
android:id="@+id/tv_video_from"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="From"
android:textSize="15sp"
android:textColor="@color/white" />
<TextView
android:id="@+id/tv_video_intro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="introduce"
android:textSize="15sp"
android:textColor="@color/white_al80" />
</LinearLayout>
<com.ama.core.common.widget.PopMenuIconView
android:id="@+id/pop_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="100dp"
android:layout_marginRight="20dp"
android:gravity="center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/home_star_undo"
/>
<TextView
android:id="@+id/tv_star_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="999"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="@color/white" />
</LinearLayout>
<ImageView
android:id="@+id/iv_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/home_share"
android:layout_marginTop="20dp"
/>
</LinearLayout>
</FrameLayout>

View File

@ -0,0 +1,13 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent" >
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,433 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
android:background="#666666"
tools:ignore="Overdraw">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="10dp"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/white_f5"
android:text="Centro de Missões"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="15dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:background="@drawable/vididinapp_feature_message_bg_task_coin"
android:padding="10dp"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/pink_0b"
android:text="Centro de Missões"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="15dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:layout_marginLeft="8dp"
android:text="12345"
/>
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:drawableLeft="@mipmap/temp"
android:drawablePadding="10dp"
android:layout_marginLeft="8dp"
android:text="Resgatar"
android:layout_gravity="center_horizontal"
android:gravity="center"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:background="@drawable/vididinapp_feature_message_bg_task_cash"
android:padding="10dp"
android:layout_marginLeft="10dp"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/pink_0b"
android:text="Meu Dinheiro"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="15dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:layout_marginLeft="8dp"
android:text="12345"
/>
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:drawableLeft="@mipmap/temp"
android:drawablePadding="10dp"
android:layout_marginLeft="8dp"
android:text="Resgatar"
android:layout_gravity="center_horizontal"
android:gravity="center"
/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:layout_marginTop="15dp"
android:background="@drawable/vididinapp_feature_message_bg_task_ativi">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:layout_marginLeft="8dp"
android:text="Atividades"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:layout_marginTop="10dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical" >
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="-10dp"
android:background="@drawable/vididinapp_feature_message_bg_task_activity"
android:text="3 dias"
android:textColor="#FFFFFF"
android:textSize="10sp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="8dp"
android:text="Benefícios"
android:textColor="#FFFF0A5C"
android:textSize="12sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical" >
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="-10dp"
android:background="@drawable/vididinapp_feature_message_bg_task_activity"
android:text="3 dias"
android:textColor="#FFFFFF"
android:textSize="10sp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="8dp"
android:text="Benefícios"
android:textColor="#FFFF0A5C"
android:textSize="12sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical" >
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="-10dp"
android:background="@drawable/vididinapp_feature_message_bg_task_activity"
android:text="3 dias"
android:textColor="#FFFFFF"
android:textSize="10sp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="8dp"
android:text="Benefícios"
android:textColor="#FFFF0A5C"
android:textSize="12sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_horizontal"
android:orientation="vertical" >
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="-10dp"
android:background="@drawable/vididinapp_feature_message_bg_task_activity"
android:text="3 dias"
android:textColor="#FFFFFF"
android:textSize="10sp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="58dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="8dp"
android:text="Benefícios"
android:textColor="#FFFF0A5C"
android:textSize="12sp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="10dp"
android:layout_marginTop="15dp"
android:background="@drawable/vididinapp_feature_message_bg_task_inici">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:layout_marginLeft="8dp"
android:text="Missão para Iniciantes"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginTop="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:background="@drawable/vididinapp_feature_message_bg_task_login">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/temp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:layout_marginLeft="10dp"
android:textColor="@color/black"
android:text="Login Diário"
/>
</LinearLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="15dp"
android:background="@drawable/vididinapp_feature_message_bg_task_fazer"
android:text="Fazer Login Agora"
android:paddingVertical="9dp"
android:textColor="#FFFFFF"
android:textSize="18sp"
/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginHorizontal="10dp"
/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="10dp"
android:layout_marginTop="15dp"
android:background="@drawable/vididinapp_feature_message_bg_task_inici">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="21sp"
android:textColor="@color/pink_0b"
android:layout_marginLeft="8dp"
android:text="Missões Diárias"
/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginHorizontal="10dp"
/>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nested_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="Overdraw">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/top_background"
android:layout_width="match_parent"
android:layout_height="0dp"
android:src="@drawable/vididinapp_feature_mine_bg_top"
app:layout_constraintDimensionRatio="642:360"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/ll_account_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:gravity="center_horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical">
<com.ama.core.common.widget.roundedimageview.RoundedImageView
android:id="@+id/avatar_view"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/temp"
tools:ignore="ContentDescription" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_account_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="18sp"
android:layout_marginTop="10dp"
android:textColor="#000000"
android:text="Miguel"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="#999999"
android:text="ID:123456"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginHorizontal="15dp"
android:gravity="center_horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ll_account_container"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="@drawable/vididinapp_feature_mine_option_bg"
>
<ImageView
android:id="@+id/iv_option_political_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_option_political"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv_option_political_left"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#333333"
android:text="Política de Privacidade"
/>
<ImageView
android:id="@+id/iv_option_political_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="@drawable/vididinapp_feature_mine_option_bg"
>
<ImageView
android:id="@+id/iv_option_versao_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_option_versao"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv_option_versao_left"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#333333"
android:text="Versão Atual"
/>
<ImageView
android:id="@+id/iv_option_versao_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="@drawable/vididinapp_feature_mine_option_bg"
>
<ImageView
android:id="@+id/iv_option_feedback_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_option_feedback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/iv_option_feedback_left"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#333333"
android:text="Feedback"
/>
<ImageView
android:id="@+id/iv_option_feedback_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/temp" />
</RelativeLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

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