commit 295b446eac262fb70bf3ed0a3bd9ce4fe86bff45 Author: litingting Date: Mon Dec 1 14:55:15 2025 +0800 V1.0(1) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/LEDScroller b/app/LEDScroller new file mode 100644 index 0000000..3b8f3f8 Binary files /dev/null and b/app/LEDScroller differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..5e03db1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,60 @@ +import java.util.Date +import java.text.SimpleDateFormat +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} +def timestamp = new Date().format("MM_dd_HH_mm") +android { + namespace 'com.led.scroller.barrage.banner' + compileSdk 36 + + defaultConfig { + applicationId "com.led.scroller.barrage.banner" + minSdk 24 + targetSdk 36 + versionCode 1 + versionName "1.0" + setProperty( + "archivesBaseName", + "LED Scroller_V" + versionName + "(${versionCode})_$timestamp" + ) + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary true + } + } + + buildTypes { + release { + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + viewBinding true + buildConfig = true + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } +} + +dependencies { + implementation 'androidx.core:core-ktx:1.17.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.9.4' + implementation 'androidx.appcompat:appcompat:1.7.1' + implementation fileTree(dir: 'libs', include: ['*.jar','*.aar']) + implementation 'com.google.android.material:material:1.13.0' + implementation 'androidx.activity:activity-ktx:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/app/src/androidTest/java/com/led/scroller/barrage/banner/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/led/scroller/barrage/banner/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..1e3ea32 --- /dev/null +++ b/app/src/androidTest/java/com/led/scroller/barrage/banner/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.led.scroller.barrage.banner + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.led.scroller.barrage.banner", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..f2d6d01 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/LBApplication.kt b/app/src/main/java/com/led/scroller/barrage/banner/LBApplication.kt new file mode 100644 index 0000000..c507ce5 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/LBApplication.kt @@ -0,0 +1,16 @@ +package com.led.scroller.barrage.banner + +import android.app.Application + +class LBApplication : Application() { + + companion object { + lateinit var app: LBApplication + } + + override fun onCreate() { + super.onCreate() + app = this + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/app/AppUtil.kt b/app/src/main/java/com/led/scroller/barrage/banner/app/AppUtil.kt new file mode 100644 index 0000000..68e3f3a --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/app/AppUtil.kt @@ -0,0 +1,36 @@ +package com.led.scroller.barrage.banner.app + +import android.content.Context +import android.graphics.drawable.GradientDrawable +import androidx.core.content.ContextCompat +import com.led.scroller.barrage.banner.R + +fun getShapeDrawable( + content: Context, + startColor: Int, + endColor: Int +): GradientDrawable { + // 创建圆角矩形形状 + val shape = GradientDrawable() + shape.shape = GradientDrawable.RECTANGLE + + // 设置形状的渐变颜色 + shape.colors = intArrayOf( + ContextCompat.getColor(content, startColor), + ContextCompat.getColor(content, endColor) + ) + + // 设置渐变方向,这里设置为从上到下的方向 + shape.orientation = GradientDrawable.Orientation.TOP_BOTTOM + + // 设置圆角半径 + val cornerRadius = content.resources.getDimension(R.dimen.corner_radius) + shape.cornerRadius = cornerRadius + + return shape +} + +fun dpToPx(dp: Float, context: Context): Float { + val scale = context.resources.displayMetrics.density + return dp * scale +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/app/Providers.kt b/app/src/main/java/com/led/scroller/barrage/banner/app/Providers.kt new file mode 100644 index 0000000..3f4f1bc --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/app/Providers.kt @@ -0,0 +1,61 @@ +package com.led.scroller.barrage.banner.app + +import android.content.SharedPreferences +import androidx.core.content.edit + +class SharedPreferenceProviderWallpaper(private val preferences: SharedPreferences) : + VariablesProvider { + override fun getInt(key: String, defaultValue: Int): Int { + return preferences.getInt(key, defaultValue) + } + + override fun setInt(key: String, value: Int) { + preferences.edit { + putInt(key, value) + } + } + + override fun getLong(key: String, defaultValue: Long): Long { + return preferences.getLong(key, defaultValue) + } + + override fun setLong(key: String, value: Long) { + preferences.edit { + putLong(key, value) + } + } + + override fun getString(key: String, defaultValue: String): String { + return preferences.getString(key, defaultValue)!! + } + + override fun setString(key: String, value: String) { + preferences.edit { + putString(key, value) + } + } + + override fun getStringSet(key: String, defaultValue: Set): Set { + return preferences.getStringSet(key, defaultValue)!! + } + + override fun setStringSet(key: String, value: Set) { + preferences.edit { + putStringSet(key, value) + } + } + + override fun getBoolean(key: String, defaultValue: Boolean): Boolean { + return preferences.getBoolean(key, defaultValue) + } + + override fun setBoolean(key: String, value: Boolean) { + preferences.edit { + putBoolean(key, value) + } + } +} + +fun SharedPreferences.asStoreProvider(): VariablesProvider { + return SharedPreferenceProviderWallpaper(this) +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/app/VariablesProvider.kt b/app/src/main/java/com/led/scroller/barrage/banner/app/VariablesProvider.kt new file mode 100644 index 0000000..3b81de6 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/app/VariablesProvider.kt @@ -0,0 +1,18 @@ +package com.led.scroller.barrage.banner.app + +interface VariablesProvider { + fun getInt(key: String, defaultValue: Int): Int + fun setInt(key: String, value: Int) + + fun getLong(key: String, defaultValue: Long): Long + fun setLong(key: String, value: Long) + + fun getString(key: String, defaultValue: String): String + fun setString(key: String, value: String) + + fun getStringSet(key: String, defaultValue: Set): Set + fun setStringSet(key: String, value: Set) + + fun getBoolean(key: String, defaultValue: Boolean): Boolean + fun setBoolean(key: String, value: Boolean) +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/bean/FontBean.kt b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontBean.kt new file mode 100644 index 0000000..4f2de97 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontBean.kt @@ -0,0 +1,8 @@ +package com.led.scroller.barrage.banner.bean + +import java.io.Serializable + +class FontBean( + var id: Int, + var select: Boolean, +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/bean/FontColorBean.kt b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontColorBean.kt new file mode 100644 index 0000000..ef16dc0 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontColorBean.kt @@ -0,0 +1,9 @@ +package com.led.scroller.barrage.banner.bean + +import java.io.Serializable + +class FontColorBean( + val id: Int, // 颜色资源 ID + val colorString: String, // 颜色值 + var select: Boolean, +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/bean/FontSizeBean.kt b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontSizeBean.kt new file mode 100644 index 0000000..6dcce01 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/bean/FontSizeBean.kt @@ -0,0 +1,9 @@ +package com.led.scroller.barrage.banner.bean + +import java.io.Serializable + +class FontSizeBean( + var name: String, + var size: Int, + var select: Boolean, +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/sp/AppSP.kt b/app/src/main/java/com/led/scroller/barrage/banner/sp/AppSP.kt new file mode 100644 index 0000000..96b6462 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/sp/AppSP.kt @@ -0,0 +1,41 @@ +package com.led.scroller.barrage.banner.sp + +import android.content.Context +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.app.asStoreProvider + +class AppSP(context: Context) { + + private val store = BaseSP( + context + .getSharedPreferences(context.packageName, Context.MODE_PRIVATE) + .asStoreProvider() + ) + + var fontResId: Int by store.int( + key = FONT_RES_ID, + defaultValue = R.font.font_medium + ) + + var fontColorResId: Int by store.int( + key = FONT_COLOR_RES_ID, + defaultValue = R.color.font_color_1 + ) + + var fontSize: Int by store.int( + key = FONT_Size, + defaultValue = 80 + ) + + var bgColorResId: Int by store.int( + key = BG_COLOR_RES_ID, + defaultValue = R.color.default_preview_bg_color + ) + + companion object { + const val FONT_RES_ID = "font_res_id" + const val FONT_COLOR_RES_ID = "font_color_res_id" + const val FONT_Size = "font_size" + const val BG_COLOR_RES_ID = "bg_color_res_id" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/sp/BaseSP.kt b/app/src/main/java/com/led/scroller/barrage/banner/sp/BaseSP.kt new file mode 100644 index 0000000..bc22324 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/sp/BaseSP.kt @@ -0,0 +1,99 @@ +package com.led.scroller.barrage.banner.sp + +import com.led.scroller.barrage.banner.app.VariablesProvider +import kotlin.reflect.KProperty + +class BaseSP(val provider: VariablesProvider) { + interface Delegate { + operator fun getValue(thisRef: Any?, property: KProperty<*>): T + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) + } + + fun int(key: String, defaultValue: Int): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): Int { + return provider.getInt(key, defaultValue) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { + provider.setInt(key, value) + } + } + } + + fun long(key: String, defaultValue: Long): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): Long { + return provider.getLong(key, defaultValue) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { + provider.setLong(key, value) + } + } + } + + fun string(key: String, defaultValue: String): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): String { + return provider.getString(key, defaultValue) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + provider.setString(key, value) + } + } + } + + fun stringSet(key: String, defaultValue: Set): Delegate> { + return object : Delegate> { + override fun getValue(thisRef: Any?, property: KProperty<*>): Set { + return provider.getStringSet(key, defaultValue) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Set) { + provider.setStringSet(key, value) + } + } + } + + fun boolean(key: String, defaultValue: Boolean): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { + return provider.getBoolean(key, defaultValue) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { + provider.setBoolean(key, value) + } + } + } + + fun > enum(key: String, defaultValue: T, values: Array): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): T { + val name = provider.getString(key, defaultValue.name) + + return values.find { name == it.name } ?: defaultValue + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { + provider.setString(key, value.name) + } + } + } + + fun typedString(key: String, from: (String) -> T?, to: (T?) -> String): Delegate { + return object : Delegate { + override fun getValue(thisRef: Any?, property: KProperty<*>): T? { + val value = provider.getString(key, to(null)) + + return from(value) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { + provider.setString(key, to(value)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/BackgroundFragment.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/BackgroundFragment.kt new file mode 100644 index 0000000..5d0dfb5 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/BackgroundFragment.kt @@ -0,0 +1,93 @@ +package com.led.scroller.barrage.banner.ui + +import android.annotation.SuppressLint +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.GridLayoutManager +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.bean.FontColorBean +import com.led.scroller.barrage.banner.databinding.FragmentBackgroundBinding +import com.led.scroller.barrage.banner.databinding.FragmentTextBinding +import com.led.scroller.barrage.banner.sp.AppSP +import com.led.scroller.barrage.banner.ui.adapter.FontColorAdapter + +class BackgroundFragment : Fragment() { + private lateinit var binding: FragmentBackgroundBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentBackgroundBinding.inflate(layoutInflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initView() + } + + override fun onResume() { + super.onResume() + // 确保监听器在Fragment可见时重新设置 + if (backgroundFragmentClickListener == null) { + Log.d("BackgroundFragment", "监听器为空,可能需要重新设置") + } + } + + private fun initView() { + initBgColorAdapter() + } + + + private fun initBgColorAdapter() { + val sp = AppSP(requireActivity()) + val bgColorId = sp.bgColorResId + val bgColorList: MutableList = mutableListOf() + // 获取颜色资源数组 + val colorArray = resources.obtainTypedArray(R.array.BgColorArray) + // 遍历颜色资源数组 + for (i in 0 until colorArray.length()) { + val colorResId = colorArray.getResourceId(i, 0) + val colorValue = ContextCompat.getColor(requireContext(), colorResId) + // 将颜色值转换为十六进制字符串 + val hexColor = String.format("#%06X", 0xFFFFFF and colorValue) + val fontColor = FontColorBean(colorResId, hexColor, colorResId == bgColorId) + bgColorList.add(fontColor) + } + colorArray.recycle() + + val fontColorAdapter = FontColorAdapter(requireActivity(), bgColorList) + fontColorAdapter.setOnItemClickListener(object : FontColorAdapter.OnItemClickListener { + @SuppressLint("NotifyDataSetChanged") + override fun onItemClick(position: Int) { + val bean = bgColorList[position] + for (fontColor in bgColorList) { + fontColor.select = false + } + bgColorList[position].select = true + AppSP(requireActivity()).bgColorResId = bean.id + fontColorAdapter.notifyDataSetChanged() + backgroundFragmentClickListener?.onBgColorClick() + } + }) + binding.colorRv.layoutManager = GridLayoutManager(requireActivity(), 7) + binding.colorRv.adapter = fontColorAdapter + } + + + private var backgroundFragmentClickListener: BackgroundFragmentClickListener? = null + fun setBackgroundFragmentClickListener(listener: BackgroundFragmentClickListener) { + backgroundFragmentClickListener = listener + } + + interface BackgroundFragmentClickListener { + fun onBgColorClick() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/BaseActivity.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/BaseActivity.kt new file mode 100644 index 0000000..3125a2f --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/BaseActivity.kt @@ -0,0 +1,18 @@ +package com.led.scroller.barrage.banner.ui + +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.led.scroller.barrage.banner.sp.AppSP + +abstract class BaseActivity : AppCompatActivity() { + private val appSp by lazy { AppSP(this) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/MainActivity.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/MainActivity.kt new file mode 100644 index 0000000..88bbdc2 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/MainActivity.kt @@ -0,0 +1,267 @@ +package com.led.scroller.barrage.banner.ui + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.annotation.SuppressLint +import android.app.ComponentCaller +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.util.TypedValue +import android.view.animation.LinearInterpolator +import androidx.activity.enableEdgeToEdge +import androidx.core.content.res.ResourcesCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.Fragment +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.databinding.ActivityMainBinding +import com.led.scroller.barrage.banner.sp.AppSP +import com.led.scroller.barrage.banner.ui.adapter.TabFragmentPagerAdapter + +class MainActivity : BaseActivity(), TextFragment.TextFragmentClickListener, + BackgroundFragment.BackgroundFragmentClickListener { + private var animSet: AnimatorSet? = null + private var animOne: ObjectAnimator? = null + private lateinit var binding: ActivityMainBinding + private var mFragments: MutableList = mutableListOf() + private var mStrings: MutableList = mutableListOf() + private lateinit var tabFragmentPagerAdapter: TabFragmentPagerAdapter + private val textFragment = TextFragment() + private val backgroundFragment = BackgroundFragment() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + binding = ActivityMainBinding.inflate(layoutInflater) + setContentView(binding.root) + immersionBar() + initView() + initTab() + animatorRightToLeft() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + Log.d("MainActivity", "onSaveInstanceState") + } + + private fun immersionBar() { + //自适应沉浸式 + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) + insets + } + + val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) + windowInsetsController.isAppearanceLightStatusBars = false//状态栏文字颜色 + } + + private fun initTab() { + mStrings.add(getString(R.string.text)) + mStrings.add(getString(R.string.background)) + mFragments.add(textFragment) + mFragments.add(backgroundFragment) + + tabFragmentPagerAdapter = + TabFragmentPagerAdapter(supportFragmentManager, mFragments, mStrings) + binding.viewPager.adapter = tabFragmentPagerAdapter + binding.tabLayout.setupWithViewPager(binding.viewPager) + + // 设置页面变化监听器,确保Fragment在显示时正确设置监听器 + binding.viewPager.addOnPageChangeListener(object : + androidx.viewpager.widget.ViewPager.OnPageChangeListener { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + } + + override fun onPageSelected(position: Int) { + Log.d("MainActivity", "页面被选中: $position") + // 当页面被选中时,确保监听器已设置 + val fragment = + supportFragmentManager.findFragmentByTag("android:switcher:${binding.viewPager.id}:$position") + Log.d("MainActivity", "找到的Fragment: $fragment") + when (fragment) { + is TextFragment -> { + Log.d("MainActivity", "设置TextFragment监听器(页面切换)") + fragment.setTextFragmentClickListener(this@MainActivity) + } + is BackgroundFragment -> { + Log.d("MainActivity", "设置BackgroundFragment监听器(页面切换)") + fragment.setBackgroundFragmentClickListener(this@MainActivity) + } + } + } + + override fun onPageScrollStateChanged(state: Int) {} + }) + } + + @SuppressLint("ClickableViewAccessibility") + private fun initView() { + //屏蔽事件 + binding.horizontalScrollview.setOnTouchListener { v, _ -> + v.parent.requestDisallowInterceptTouchEvent(true) + true + } + binding.startBtn.setOnClickListener { + val content = binding.contentEdit.text.toString() + if (content.isNotEmpty()) { + val intent = Intent(this, ShowBarrageActivity::class.java) + intent.putExtra(ShowBarrageActivity.CONTENT_KEY, content) + startActivity(intent) + } else { + showToast(getString(R.string.type_something)) + } + } + binding.contentEdit.addTextChangedListener { + updatePreviewText() + } + } + + private var content = "" + private fun updatePreviewText() { + content = binding.contentEdit.text.toString() + val sp = AppSP(this) + binding.previewLayout.setBackgroundColor(getColor(sp.bgColorResId)) + binding.previewText.text = content + binding.previewText.setTextColor(getColor(sp.fontColorResId)) + binding.previewText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, sp.fontSize.toFloat()) + val typeface = ResourcesCompat.getFont(this, sp.fontResId) + binding.previewText.typeface = typeface + } + + private fun animatorRightToLeft() { + val textPaint = binding.previewText.paint + val textPaintWidth = textPaint.measureText(content) //获取文字的宽度。 + val screenWidth = resources.displayMetrics.widthPixels //获取屏幕的宽度。 + animSet = AnimatorSet() + animSet?.interpolator = LinearInterpolator() //线性 + animOne = ObjectAnimator.ofFloat( + binding.previewText, + "translationX", + screenWidth.toString().toFloat(), + -textPaintWidth + ) //X轴移动,屏幕宽度为起始值,也就是会从最右边开始到看不到文字。 + animOne?.duration = 5000 + animOne?.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + animatorRightToLeft() + } + }) + animSet?.play(animOne) + animSet?.start() + } + + override fun onPause() { + super.onPause() + pauseAnimation() + } + + override fun onResume() { + super.onResume() + Log.d("MainActivity", "onResume()被调用") + resumeAnimation() + updatePreviewText() + + // 延迟重置监听器,确保Fragment完全恢复 + binding.viewPager.post { + Log.d("MainActivity", "延迟重置Fragment监听器") + resetFragmentListeners() + + // 强制重新创建适配器作为最后手段 + if (tabFragmentPagerAdapter != null) { + Log.d("MainActivity", "重新创建适配器") + tabFragmentPagerAdapter = TabFragmentPagerAdapter(supportFragmentManager, mFragments, mStrings) + binding.viewPager.adapter = tabFragmentPagerAdapter + binding.tabLayout.setupWithViewPager(binding.viewPager) + + // 重新设置监听器 + binding.viewPager.postDelayed({ + resetFragmentListeners() + }, 100) + } + } + } + + override fun onRestart() { + super.onRestart() + Log.d("MainActivity", "onRestart()被调用") + } + + override fun onStart() { + super.onStart() + Log.d("MainActivity", "onStart()被调用") + } + + private fun resetFragmentListeners() { + Log.d("MainActivity", "开始重置Fragment监听器") + + // 方法1:尝试通过ViewPager获取当前Fragment实例 + val currentTextFragment = supportFragmentManager.findFragmentByTag("android:switcher:${binding.viewPager.id}:0") as? TextFragment + val currentBackgroundFragment = supportFragmentManager.findFragmentByTag("android:switcher:${binding.viewPager.id}:1") as? BackgroundFragment + + Log.d("MainActivity", "当前TextFragment实例: $currentTextFragment, 保存的实例: $textFragment") + Log.d("MainActivity", "当前BackgroundFragment实例: $currentBackgroundFragment, 保存的实例: $backgroundFragment") + + // 方法2:设置到当前活动的Fragment实例 + currentTextFragment?.let { fragment -> + Log.d("MainActivity", "设置当前TextFragment监听器") + fragment.setTextFragmentClickListener(this) + } + + currentBackgroundFragment?.let { fragment -> + Log.d("MainActivity", "设置当前BackgroundFragment监听器") + fragment.setBackgroundFragmentClickListener(this) + } + + // 方法3:同时设置到保存的实例(作为备份) + textFragment.setTextFragmentClickListener(this) + backgroundFragment.setBackgroundFragmentClickListener(this) + + // 方法4:强制刷新ViewPager的当前页面 + val currentItem = binding.viewPager.currentItem + if (currentItem == 0) { + currentTextFragment?.setTextFragmentClickListener(this) + } else if (currentItem == 1) { + currentBackgroundFragment?.setBackgroundFragmentClickListener(this) + } + + Log.d("MainActivity", "Fragment监听器重置完成") + } + + private fun pauseAnimation() { + animSet?.pause() + } + + private fun resumeAnimation() { + animSet?.resume() + } + + override fun onFontItemClick() { + Log.d("MainActivity", "收到onFontItemClick回调") + updatePreviewText() + } + + override fun onFontColorItemClick() { + Log.d("MainActivity", "收到onFontColorItemClick回调") + updatePreviewText() + } + + override fun onFontSizeItemClick() { + Log.d("MainActivity", "收到onFontSizeItemClick回调") + updatePreviewText() + } + + override fun onBgColorClick() { + Log.d("MainActivity", "收到onBgColorClick回调") + updatePreviewText() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/ShowBarrageActivity.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/ShowBarrageActivity.kt new file mode 100644 index 0000000..314ac2b --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/ShowBarrageActivity.kt @@ -0,0 +1,101 @@ +package com.led.scroller.barrage.banner.ui + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.os.Bundle +import android.util.Log +import android.util.TypedValue +import android.view.View +import android.view.animation.LinearInterpolator +import androidx.activity.ComponentActivity +import androidx.core.content.res.ResourcesCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat +import com.led.scroller.barrage.banner.databinding.ActivityShowBarrageBinding +import com.led.scroller.barrage.banner.sp.AppSP +import androidx.core.view.isVisible + +class ShowBarrageActivity : ComponentActivity() { + companion object { + const val CONTENT_KEY = "content_key" + } + + private var animSet: AnimatorSet? = null + private var animOne: ObjectAnimator? = null + private lateinit var binding: ActivityShowBarrageBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityShowBarrageBinding.inflate(layoutInflater) + setContentView(binding.root) + val controller = WindowCompat.getInsetsController(window, window.decorView) + hideSystemBars(controller) + initView() + val content = intent.getStringExtra(CONTENT_KEY) + animatorRightToLeft(content.toString()) + } + + private fun hideSystemBars(controller: WindowInsetsControllerCompat) { + // 让导航栏和状态栏完全隐藏 + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + controller.hide(WindowInsetsCompat.Type.systemBars()) + } + + private fun initView() { + binding.root.setOnClickListener { + if (binding.backImg.isVisible) { + binding.backImg.visibility = View.GONE + } else { + binding.backImg.visibility = View.VISIBLE + } + } + binding.backImg.setOnClickListener { + Log.d("ShowBarrageActivity", "返回按钮点击,调用finish()") + finish() + } + } + + override fun onBackPressed() { + Log.d("ShowBarrageActivity", "系统返回键被按下") + super.onBackPressed() + } + + override fun finish() { + Log.d("ShowBarrageActivity", "finish()被调用") + super.finish() + } + + private fun animatorRightToLeft(content: String) { + val sp = AppSP(this) + binding.previewLayout.setBackgroundColor(getColor(sp.bgColorResId)) + binding.previewText.text = content + binding.previewText.setTextColor(getColor(sp.fontColorResId)) + binding.previewText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, sp.fontSize.toFloat()) + // 加载字体文件 + val typeface = ResourcesCompat.getFont(this, sp.fontResId) + binding.previewText.typeface = typeface + + val textPaint = binding.previewText.paint + val textPaintWidth = textPaint.measureText(content) //获取文字的宽度。 + val screenWidth = resources.displayMetrics.widthPixels //获取屏幕的宽度。 + animSet = AnimatorSet() + animSet?.interpolator = LinearInterpolator() //线性 + animOne = ObjectAnimator.ofFloat( + binding.previewText, + "translationX", + screenWidth.toString().toFloat(), + -textPaintWidth + ) //X轴移动,屏幕宽度为起始值,也就是会从最右边开始到看不到文字。 + animOne?.duration = 5000 + animOne?.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + animatorRightToLeft(content) + } + }) + animSet?.play(animOne) + animSet?.start() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/TextFragment.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/TextFragment.kt new file mode 100644 index 0000000..c0a729f --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/TextFragment.kt @@ -0,0 +1,168 @@ +package com.led.scroller.barrage.banner.ui + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.GradientDrawable +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.GridLayoutManager +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.bean.FontColorBean +import com.led.scroller.barrage.banner.bean.FontBean +import com.led.scroller.barrage.banner.bean.FontSizeBean +import com.led.scroller.barrage.banner.databinding.FragmentTextBinding +import com.led.scroller.barrage.banner.sp.AppSP +import com.led.scroller.barrage.banner.ui.adapter.FontColorAdapter +import com.led.scroller.barrage.banner.ui.adapter.FontAdapter +import com.led.scroller.barrage.banner.ui.adapter.FontSizeAdapter + +class TextFragment : Fragment() { + private lateinit var binding: FragmentTextBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentTextBinding.inflate(layoutInflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initView() + } + + override fun onResume() { + super.onResume() + // 确保监听器在Fragment可见时重新设置 + if (textFragmentClickListener == null) { + Log.d("TextFragment", "监听器为空,可能需要重新设置") + } + } + + private fun initView() { + initFontAdapter() + initColorAdapter() + initFontSizeAdapter() + } + + private fun initFontAdapter() { + val fontList: MutableList = mutableListOf() + val sp = AppSP(requireActivity()) + val fontID = sp.fontResId + fontList.add(FontBean(R.font.font_medium, R.font.font_medium == fontID)) + fontList.add(FontBean(R.font.header, R.font.header == fontID)) + fontList.add(FontBean(R.font.damion, R.font.damion == fontID)) + fontList.add(FontBean(R.font.grandma, R.font.grandma == fontID)) + fontList.add(FontBean(R.font.playball, R.font.playball == fontID)) + fontList.add(FontBean(R.font.pork, R.font.pork == fontID)) + fontList.add(FontBean(R.font.silver, R.font.silver == fontID)) + + val fontAdapter = FontAdapter(requireActivity(), fontList) + fontAdapter.setOnItemClickListener(object : FontAdapter.OnItemClickListener { + @SuppressLint("NotifyDataSetChanged") + override fun onItemClick(position: Int) { + val bean = fontList[position] + for (font in fontList) { + font.select = false + } + fontList[position].select = true + AppSP(requireActivity()).fontResId = bean.id + fontAdapter.notifyDataSetChanged() + Log.d("TextFragment", "触发onFontItemClick, 监听器: $textFragmentClickListener") + textFragmentClickListener?.onFontItemClick() + } + }) + binding.fontRv.layoutManager = GridLayoutManager(requireActivity(), 7) + binding.fontRv.adapter = fontAdapter + } + + private fun initColorAdapter() { + val sp = AppSP(requireActivity()) + val fontColorId = sp.fontColorResId + val fontColorList: MutableList = mutableListOf() + // 获取颜色资源数组 + val colorArray = resources.obtainTypedArray(R.array.FontColorArray) + // 遍历颜色资源数组 + for (i in 0 until colorArray.length()) { + val colorResId = colorArray.getResourceId(i, 0) + val colorValue = ContextCompat.getColor(requireContext(), colorResId) + // 将颜色值转换为十六进制字符串 + val hexColor = String.format("#%06X", 0xFFFFFF and colorValue) + val fontColor = FontColorBean(colorResId, hexColor, colorResId == fontColorId) + fontColorList.add(fontColor) + } + colorArray.recycle() + + val fontColorAdapter = FontColorAdapter(requireActivity(), fontColorList) + fontColorAdapter.setOnItemClickListener(object : FontColorAdapter.OnItemClickListener { + @SuppressLint("NotifyDataSetChanged") + override fun onItemClick(position: Int) { + val bean = fontColorList[position] + for (fontColor in fontColorList) { + fontColor.select = false + } + fontColorList[position].select = true + AppSP(requireActivity()).fontColorResId = bean.id + fontColorAdapter.notifyDataSetChanged() + Log.d("TextFragment", "触发onFontColorItemClick, 监听器: $textFragmentClickListener") + textFragmentClickListener?.onFontColorItemClick() + } + }) + binding.colorRv.layoutManager = GridLayoutManager(requireActivity(), 7) + binding.colorRv.adapter = fontColorAdapter + } + + private fun initFontSizeAdapter() { + val sp = AppSP(requireActivity()) + val fontSize = sp.fontSize + val fontSizeList: MutableList = mutableListOf() + // 获取字符串资源数组 + val fontSizeNameArray = resources.getStringArray(R.array.FontSizeNameArray) + val fontSizeArray = resources.getIntArray(R.array.FontSizeArray) + // 确保两个数组的长度相同 + if (fontSizeNameArray.size == fontSizeArray.size) { + for (i in fontSizeNameArray.indices) { + val name = fontSizeNameArray[i] + val size = fontSizeArray[i] + val fontSizeBean = FontSizeBean(name, size, fontSize == size) + fontSizeList.add(fontSizeBean) + } + } + val fontSizeAdapter = FontSizeAdapter(requireActivity(), fontSizeList) + fontSizeAdapter.setOnItemClickListener(object : FontSizeAdapter.OnItemClickListener { + @SuppressLint("NotifyDataSetChanged") + override fun onItemClick(position: Int) { + val bean = fontSizeList[position] + for (size in fontSizeList) { + size.select = false + } + fontSizeList[position].select = true + AppSP(requireActivity()).fontSize = bean.size + fontSizeAdapter.notifyDataSetChanged() + Log.d("TextFragment", "触发onFontSizeItemClick, 监听器: $textFragmentClickListener") + textFragmentClickListener?.onFontSizeItemClick() + } + }) + binding.sizeRv.layoutManager = GridLayoutManager(requireActivity(), fontSizeList.size) + binding.sizeRv.adapter = fontSizeAdapter + } + + private var textFragmentClickListener: TextFragmentClickListener? = null + fun setTextFragmentClickListener(listener: TextFragmentClickListener) { + Log.d("TextFragment", "设置监听器: $listener") + textFragmentClickListener = listener + } + + interface TextFragmentClickListener { + fun onFontItemClick() + fun onFontColorItemClick() + fun onFontSizeItemClick() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontAdapter.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontAdapter.kt new file mode 100644 index 0000000..cfe8d3d --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontAdapter.kt @@ -0,0 +1,61 @@ +package com.led.scroller.barrage.banner.ui.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Typeface +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.content.res.ResourcesCompat +import androidx.recyclerview.widget.RecyclerView +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.bean.FontBean +import com.led.scroller.barrage.banner.databinding.AdapterFontItemBinding + +class FontAdapter( + private val context: Context, + private val fontList: MutableList, +) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FontViewHolder { + val inflater = LayoutInflater.from(context) + val binding = AdapterFontItemBinding.inflate(inflater, parent, false) + return FontViewHolder(binding) + } + + @SuppressLint("UseCompatLoadingForDrawables") + override fun onBindViewHolder(holder: FontViewHolder, position: Int) { + val bean = fontList[position] + val typeface = ResourcesCompat.getFont(context, bean.id) + holder.binding.textView.typeface = typeface + if (bean.select) { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_selected) + } else { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_unselected) + } + holder.itemView.setOnClickListener { + if (itemClickListener != null) { + itemClickListener?.onItemClick(position) + } + } + } + + override fun getItemCount(): Int { + return fontList.size + } + + inner class FontViewHolder(val binding: AdapterFontItemBinding) : + RecyclerView.ViewHolder(binding.root) + + private var itemClickListener: OnItemClickListener? = null + + fun setOnItemClickListener(listener: OnItemClickListener) { + itemClickListener = listener + } + + interface OnItemClickListener { + fun onItemClick(position: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontColorAdapter.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontColorAdapter.kt new file mode 100644 index 0000000..e316240 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontColorAdapter.kt @@ -0,0 +1,58 @@ +package com.led.scroller.barrage.banner.ui.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.bean.FontColorBean +import com.led.scroller.barrage.banner.databinding.AdapterColorItemBinding + +class FontColorAdapter( + private val context: Context, + private val colorList: MutableList, +) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColorViewHolder { + val inflater = LayoutInflater.from(context) + val binding = AdapterColorItemBinding.inflate(inflater, parent, false) + return ColorViewHolder(binding) + } + + @SuppressLint("UseCompatLoadingForDrawables") + override fun onBindViewHolder(holder: ColorViewHolder, position: Int) { + val bean = colorList[position] + holder.binding.bgView.setCircleColor(bean.colorString) + if (bean.select) { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_selected) + } else { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_unselected) + } + holder.itemView.setOnClickListener { + if (itemClickListener != null) { + itemClickListener?.onItemClick(position) + } + } + } + + override fun getItemCount(): Int { + return colorList.size + } + + inner class ColorViewHolder(val binding: AdapterColorItemBinding) : + RecyclerView.ViewHolder(binding.root) + + private var itemClickListener: OnItemClickListener? = null + + fun setOnItemClickListener(listener: OnItemClickListener) { + itemClickListener = listener + } + + interface OnItemClickListener { + fun onItemClick(position: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontSizeAdapter.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontSizeAdapter.kt new file mode 100644 index 0000000..991cc62 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/FontSizeAdapter.kt @@ -0,0 +1,61 @@ +package com.led.scroller.barrage.banner.ui.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.provider.FontsContractCompat +import androidx.recyclerview.widget.RecyclerView +import com.led.scroller.barrage.banner.R +import com.led.scroller.barrage.banner.bean.FontColorBean +import com.led.scroller.barrage.banner.bean.FontSizeBean +import com.led.scroller.barrage.banner.databinding.AdapterColorItemBinding +import com.led.scroller.barrage.banner.databinding.AdapterFontItemBinding + +class FontSizeAdapter( + private val context: Context, + private val fontSizeList: MutableList, +) : + RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FontSizeViewHolder { + val inflater = LayoutInflater.from(context) + val binding = AdapterFontItemBinding.inflate(inflater, parent, false) + return FontSizeViewHolder(binding) + } + + @SuppressLint("UseCompatLoadingForDrawables") + override fun onBindViewHolder(holder: FontSizeViewHolder, position: Int) { + val bean = fontSizeList[position] + holder.binding.textView.text = bean.name + if (bean.select) { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_selected) + } else { + holder.binding.selectView.background = + context.getDrawable(R.drawable.drw_round_stroke_unselected) + } + holder.itemView.setOnClickListener { + if (itemClickListener != null) { + itemClickListener?.onItemClick(position) + } + } + } + + override fun getItemCount(): Int { + return fontSizeList.size + } + + inner class FontSizeViewHolder(val binding: AdapterFontItemBinding) : + RecyclerView.ViewHolder(binding.root) + + private var itemClickListener: OnItemClickListener? = null + + fun setOnItemClickListener(listener: OnItemClickListener) { + itemClickListener = listener + } + + interface OnItemClickListener { + fun onItemClick(position: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/TabFragmentPagerAdapter.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/TabFragmentPagerAdapter.kt new file mode 100644 index 0000000..b00d745 --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/adapter/TabFragmentPagerAdapter.kt @@ -0,0 +1,22 @@ +package com.led.scroller.barrage.banner.ui.adapter + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter + +class TabFragmentPagerAdapter( + fm: FragmentManager, + private val mFragments: List, + private val mTiles: List +) : FragmentStatePagerAdapter(fm) { + + override fun getCount(): Int = mFragments.size + + override fun getItem(i: Int): Fragment { + return mFragments[i] + } + + override fun getPageTitle(position: Int): CharSequence { + return mTiles[position] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/led/scroller/barrage/banner/ui/view/CircleView.kt b/app/src/main/java/com/led/scroller/barrage/banner/ui/view/CircleView.kt new file mode 100644 index 0000000..0404bcc --- /dev/null +++ b/app/src/main/java/com/led/scroller/barrage/banner/ui/view/CircleView.kt @@ -0,0 +1,60 @@ +package com.led.scroller.barrage.banner.ui.view + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View + +class CircleView : View { + private var circleColor: Int = Color.BLACK + private val paint: Paint = Paint() + + constructor(context: Context) : super(context) { + init(null) + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + init(attrs) + } + + private fun init(attrs: AttributeSet?) { + // 初始化画笔 + paint.isAntiAlias = true // 设置抗锯齿 + paint.style = Paint.Style.FILL + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + val centerX = width / 2.toFloat() + val centerY = height / 2.toFloat() + val radius = (width.coerceAtMost(height) / 2).toFloat() + + // 设置圆的颜色 + paint.color = circleColor + + // 绘制圆形 + canvas.drawCircle(centerX, centerY, radius, paint) + } + + fun setCircleColor(color: Int) { + circleColor = color + invalidate() // 通知 View 进行重绘 + } + + fun setCircleColor(color: String) { + circleColor = Color.parseColor(color) + invalidate() // 通知 View 进行重绘 + } +} + diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/back_shadow_bg_icon.xml b/app/src/main/res/drawable/back_shadow_bg_icon.xml new file mode 100644 index 0000000..97f999c --- /dev/null +++ b/app/src/main/res/drawable/back_shadow_bg_icon.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/drw_bg_stroke_preview.xml b/app/src/main/res/drawable/drw_bg_stroke_preview.xml new file mode 100644 index 0000000..1d7ad81 --- /dev/null +++ b/app/src/main/res/drawable/drw_bg_stroke_preview.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_btn_bg.xml b/app/src/main/res/drawable/drw_btn_bg.xml new file mode 100644 index 0000000..fd0b4ad --- /dev/null +++ b/app/src/main/res/drawable/drw_btn_bg.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_frame_edit_bg.xml b/app/src/main/res/drawable/drw_frame_edit_bg.xml new file mode 100644 index 0000000..9f31c00 --- /dev/null +++ b/app/src/main/res/drawable/drw_frame_edit_bg.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_round_16_preview_bg.xml b/app/src/main/res/drawable/drw_round_16_preview_bg.xml new file mode 100644 index 0000000..9df302c --- /dev/null +++ b/app/src/main/res/drawable/drw_round_16_preview_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_round_black.xml b/app/src/main/res/drawable/drw_round_black.xml new file mode 100644 index 0000000..d0c4607 --- /dev/null +++ b/app/src/main/res/drawable/drw_round_black.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_round_stroke_selected.xml b/app/src/main/res/drawable/drw_round_stroke_selected.xml new file mode 100644 index 0000000..9d323fc --- /dev/null +++ b/app/src/main/res/drawable/drw_round_stroke_selected.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_round_stroke_unselected.xml b/app/src/main/res/drawable/drw_round_stroke_unselected.xml new file mode 100644 index 0000000..21992b3 --- /dev/null +++ b/app/src/main/res/drawable/drw_round_stroke_unselected.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drw_tab_bg.xml b/app/src/main/res/drawable/drw_tab_bg.xml new file mode 100644 index 0000000..4676be7 --- /dev/null +++ b/app/src/main/res/drawable/drw_tab_bg.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/logo.jpg b/app/src/main/res/drawable/logo.jpg new file mode 100644 index 0000000..3e1a31d Binary files /dev/null and b/app/src/main/res/drawable/logo.jpg differ diff --git a/app/src/main/res/drawable/logo_round.jpg b/app/src/main/res/drawable/logo_round.jpg new file mode 100644 index 0000000..c40f97e Binary files /dev/null and b/app/src/main/res/drawable/logo_round.jpg differ diff --git a/app/src/main/res/drawable/send_icon.xml b/app/src/main/res/drawable/send_icon.xml new file mode 100644 index 0000000..3764788 --- /dev/null +++ b/app/src/main/res/drawable/send_icon.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/setting_icon.xml b/app/src/main/res/drawable/setting_icon.xml new file mode 100644 index 0000000..244a38f --- /dev/null +++ b/app/src/main/res/drawable/setting_icon.xml @@ -0,0 +1,20 @@ + + + + diff --git a/app/src/main/res/drawable/tab_slider.xml b/app/src/main/res/drawable/tab_slider.xml new file mode 100644 index 0000000..ccbd822 --- /dev/null +++ b/app/src/main/res/drawable/tab_slider.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/font/damion.ttf b/app/src/main/res/font/damion.ttf new file mode 100644 index 0000000..d0548dd Binary files /dev/null and b/app/src/main/res/font/damion.ttf differ diff --git a/app/src/main/res/font/font_bold.ttf b/app/src/main/res/font/font_bold.ttf new file mode 100644 index 0000000..ae33a45 Binary files /dev/null and b/app/src/main/res/font/font_bold.ttf differ diff --git a/app/src/main/res/font/font_medium.ttf b/app/src/main/res/font/font_medium.ttf new file mode 100644 index 0000000..88d70b8 Binary files /dev/null and b/app/src/main/res/font/font_medium.ttf differ diff --git a/app/src/main/res/font/font_regular.ttf b/app/src/main/res/font/font_regular.ttf new file mode 100644 index 0000000..626355a Binary files /dev/null and b/app/src/main/res/font/font_regular.ttf differ diff --git a/app/src/main/res/font/grandma.otf b/app/src/main/res/font/grandma.otf new file mode 100644 index 0000000..7d04176 Binary files /dev/null and b/app/src/main/res/font/grandma.otf differ diff --git a/app/src/main/res/font/header.ttf b/app/src/main/res/font/header.ttf new file mode 100644 index 0000000..3729151 Binary files /dev/null and b/app/src/main/res/font/header.ttf differ diff --git a/app/src/main/res/font/playball.ttf b/app/src/main/res/font/playball.ttf new file mode 100644 index 0000000..15181a4 Binary files /dev/null and b/app/src/main/res/font/playball.ttf differ diff --git a/app/src/main/res/font/pork.otf b/app/src/main/res/font/pork.otf new file mode 100644 index 0000000..7fa278c Binary files /dev/null and b/app/src/main/res/font/pork.otf differ diff --git a/app/src/main/res/font/silver.ttf b/app/src/main/res/font/silver.ttf new file mode 100644 index 0000000..a5b3984 Binary files /dev/null and b/app/src/main/res/font/silver.ttf differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..9393546 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_show_barrage.xml b/app/src/main/res/layout/activity_show_barrage.xml new file mode 100644 index 0000000..9731e54 --- /dev/null +++ b/app/src/main/res/layout/activity_show_barrage.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_color_item.xml b/app/src/main/res/layout/adapter_color_item.xml new file mode 100644 index 0000000..c52ca56 --- /dev/null +++ b/app/src/main/res/layout/adapter_color_item.xml @@ -0,0 +1,23 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_font_item.xml b/app/src/main/res/layout/adapter_font_item.xml new file mode 100644 index 0000000..9708197 --- /dev/null +++ b/app/src/main/res/layout/adapter_font_item.xml @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_background.xml b/app/src/main/res/layout/fragment_background.xml new file mode 100644 index 0000000..17aacf1 --- /dev/null +++ b/app/src/main/res/layout/fragment_background.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_text.xml b/app/src/main/res/layout/fragment_text.xml new file mode 100644 index 0000000..ae8018a --- /dev/null +++ b/app/src/main/res/layout/fragment_text.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/icon.png b/app/src/main/res/mipmap-xxxhdpi/icon.png new file mode 100644 index 0000000..70202d4 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon.png differ diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml new file mode 100644 index 0000000..b0a4ef7 --- /dev/null +++ b/app/src/main/res/values/arrays.xml @@ -0,0 +1,46 @@ + + + + @color/font_color_1 + @color/font_color_2 + @color/font_color_3 + @color/font_color_4 + @color/font_color_5 + @color/font_color_6 + @color/font_color_7 + @color/font_color_8 + @color/font_color_9 + @color/font_color_10 + @color/font_color_11 + @color/font_color_12 + + + @color/default_preview_bg_color + @color/bg_color_1 + @color/bg_color_2 + @color/bg_color_3 + @color/bg_color_4 + @color/bg_color_5 + @color/bg_color_6 + @color/bg_color_7 + @color/bg_color_8 + @color/bg_color_9 + @color/bg_color_10 + @color/bg_color_11 + @color/bg_color_12 + + + @string/xs + @string/s + @string/m + @string/l + @string/xl + + + 48 + 64 + 80 + 96 + 112 + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..356db29 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,46 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #33000000 + #FFFFFFFF + #33FFFFFF + #000000 + #26FFCB + #000000 + #ffffff + #999999 + #EDFFFB + #26FFCB + #222222 + #00ffffff + #000000 + #ffffff + #51C7FC + #FFCE00 + #FF9600 + #FF2351 + #1AEC94 + #1E1AEA + #E91D1D + #5552DA + #29FEBD + #FF15C9 + + #000000 + #ffffff + #51C7FC + #FFCE00 + #FF9600 + #FF2351 + #1AEC94 + #1E1AEA + #E91D1D + #5552DA + #29FEBD + #FF15C9 + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..35aa44f --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 16dp + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..6a762dd --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,16 @@ + + LED Scroller + Type something… + Text + Background + Font + Color + Size + Speed + XS + S + M + L + XL + Play + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..2352ef0 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..6b193d2 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 0000000..fa0f996 --- /dev/null +++ b/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 0000000..9ee9997 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/test/java/com/led/scroller/barrage/banner/ExampleUnitTest.kt b/app/src/test/java/com/led/scroller/barrage/banner/ExampleUnitTest.kt new file mode 100644 index 0000000..c5ad2cd --- /dev/null +++ b/app/src/test/java/com/led/scroller/barrage/banner/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.led.scroller.barrage.banner + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..4a39479 --- /dev/null +++ b/build.gradle @@ -0,0 +1,6 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id 'com.android.application' version '8.9.1' apply false + id 'com.android.library' version '8.9.1' apply false + id 'org.jetbrains.kotlin.android' version '2.2.21' apply false +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..3c5031e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..c5feec9 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Nov 19 10:36:22 CST 2025 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/keystore.properties b/keystore.properties new file mode 100644 index 0000000..c7acb8e --- /dev/null +++ b/keystore.properties @@ -0,0 +1,6 @@ +app_name=LED Scroller +package_name=com.led.scroller.barrage.banner +keystoreFile=app/LEDScroller +key_alias=LEDScrollerkey0 +key_store_password=LEDScroller +key_password=LEDScroller diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..4269060 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "LED Scroller" +include ':app'