| <set> | <set> | ||||
| <option value="$PROJECT_DIR$" /> | <option value="$PROJECT_DIR$" /> | ||||
| <option value="$PROJECT_DIR$/app" /> | <option value="$PROJECT_DIR$/app" /> | ||||
| <option value="$PROJECT_DIR$/lib" /> | |||||
| <option value="$PROJECT_DIR$/lib/common" /> | |||||
| </set> | </set> | ||||
| </option> | </option> | ||||
| <option name="resolveModulePerSourceSet" value="false" /> | <option name="resolveModulePerSourceSet" value="false" /> |
| <option name="filePathToZoomLevelMap"> | <option name="filePathToZoomLevelMap"> | ||||
| <map> | <map> | ||||
| <entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_fullscreen.xml" value="0.10144927536231885" /> | <entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_fullscreen.xml" value="0.10144927536231885" /> | ||||
| <entry key="..\:/Work/XKL/XklLocal/app/src/main/res/layout/activity_main.xml" value="0.1" /> | |||||
| </map> | </map> | ||||
| </option> | </option> | ||||
| </component> | </component> |
| gradle 版本管理 | |||||
| ext.android : app版本信息 | |||||
| ext.version : 依赖包版本信息 | |||||
| ext.dependencies_required : 必须的依赖项 | |||||
| ext.dependencies_testImplementation : 测试依赖 | |||||
| ext.dependencies_androidTestImplementation : 测试依赖 | |||||
| ext.dependencies_custom : 自己添加的依赖项,按需定制 | |||||
| app: | |||||
| module : 按模块进行业务划分 | |||||
| common: | |||||
| app: 获取application | |||||
| base: 存放业务的基础类 | |||||
| eventbus: livedata的事件总线 | |||||
| util : 工具类,包含Kotlin的扩展属性 |
| id 'com.android.application' | id 'com.android.application' | ||||
| id 'kotlin-android' | id 'kotlin-android' | ||||
| } | } | ||||
| def androidConfig = rootProject.ext.android | |||||
| android { | android { | ||||
| compileSdk rootProject.ext.compile_sdk_version | |||||
| compileSdk androidConfig.compile_sdk_version | |||||
| buildToolsVersion androidConfig.build_tools_version | |||||
| defaultConfig { | defaultConfig { | ||||
| applicationId "com.xkl.cdl" | |||||
| minSdk 21 | |||||
| targetSdk 30 | |||||
| versionCode 1 | |||||
| versionName "1.0" | |||||
| applicationId androidConfig.applicationId | |||||
| minSdk androidConfig.min_sdk_version | |||||
| targetSdk androidConfig.target_sdk_version | |||||
| versionCode androidConfig.version_code | |||||
| versionName androidConfig.version_name | |||||
| testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||||
| } | } | ||||
| } | } | ||||
| dependencies { | dependencies { | ||||
| implementation 'androidx.core:core-ktx:1.3.2' | |||||
| implementation 'androidx.appcompat:appcompat:1.2.0' | implementation 'androidx.appcompat:appcompat:1.2.0' | ||||
| implementation 'com.google.android.material:material:1.3.0' | implementation 'com.google.android.material:material:1.3.0' | ||||
| testImplementation 'junit:junit:4.+' | |||||
| androidTestImplementation 'androidx.test.ext:junit:1.1.2' | |||||
| androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' | |||||
| implementation 'androidx.constraintlayout:constraintlayout:2.0.4' | |||||
| implementation 'androidx.legacy:legacy-support-v4:1.0.0' | |||||
| rootProject.ext.dependencies_required.each{ k, v -> implementation v} | |||||
| testImplementation rootProject.ext.dependencies_testImplementation.junit | |||||
| rootProject.ext.dependencies_androidTestImplementation.each{ k,v -> androidTestImplementation v} | |||||
| } | } |
| android:supportsRtl="true" | android:supportsRtl="true" | ||||
| android:theme="@style/Theme.XklLocal"> | android:theme="@style/Theme.XklLocal"> | ||||
| <activity | <activity | ||||
| android:name=".FullscreenActivity" | |||||
| android:name=".module.main.MainActivity" | |||||
| android:configChanges="orientation|keyboardHidden|screenSize" | android:configChanges="orientation|keyboardHidden|screenSize" | ||||
| android:exported="true" | |||||
| android:label="@string/app_name" | |||||
| android:theme="@style/Theme.XklLocal.Fullscreen"> | |||||
| android:exported="true" > | |||||
| <intent-filter> | <intent-filter> | ||||
| <action android:name="android.intent.action.MAIN" /> | <action android:name="android.intent.action.MAIN" /> | ||||
| <category android:name="android.intent.category.LAUNCHER" /> | <category android:name="android.intent.category.LAUNCHER" /> | ||||
| </intent-filter> | </intent-filter> | ||||
| </activity> | </activity> |
| package com.xkl.cdl | |||||
| import androidx.appcompat.app.AppCompatActivity | |||||
| import android.annotation.SuppressLint | |||||
| import android.os.Build | |||||
| import android.os.Bundle | |||||
| import android.os.Handler | |||||
| import android.view.MotionEvent | |||||
| import android.view.View | |||||
| import android.view.WindowInsets | |||||
| import android.widget.LinearLayout | |||||
| import android.widget.TextView | |||||
| import com.xkl.cdl.databinding.ActivityFullscreenBinding | |||||
| /** | |||||
| * An example full-screen activity that shows and hides the system UI (i.e. | |||||
| * status bar and navigation/system bar) with user interaction. | |||||
| */ | |||||
| class FullscreenActivity : AppCompatActivity() { | |||||
| private lateinit var binding: ActivityFullscreenBinding | |||||
| private lateinit var fullscreenContent: TextView | |||||
| private lateinit var fullscreenContentControls: LinearLayout | |||||
| private val hideHandler = Handler() | |||||
| @SuppressLint("InlinedApi") | |||||
| private val hidePart2Runnable = Runnable { | |||||
| // Delayed removal of status and navigation bar | |||||
| if (Build.VERSION.SDK_INT >= 30) { | |||||
| fullscreenContent.windowInsetsController?.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) | |||||
| } else { | |||||
| // Note that some of these constants are new as of API 16 (Jelly Bean) | |||||
| // and API 19 (KitKat). It is safe to use them, as they are inlined | |||||
| // at compile-time and do nothing on earlier devices. | |||||
| fullscreenContent.systemUiVisibility = | |||||
| View.SYSTEM_UI_FLAG_LOW_PROFILE or | |||||
| View.SYSTEM_UI_FLAG_FULLSCREEN or | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE or | |||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or | |||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | |||||
| } | |||||
| } | |||||
| private val showPart2Runnable = Runnable { | |||||
| // Delayed display of UI elements | |||||
| supportActionBar?.show() | |||||
| fullscreenContentControls.visibility = View.VISIBLE | |||||
| } | |||||
| private var isFullscreen: Boolean = false | |||||
| private val hideRunnable = Runnable { hide() } | |||||
| /** | |||||
| * Touch listener to use for in-layout UI controls to delay hiding the | |||||
| * system UI. This is to prevent the jarring behavior of controls going away | |||||
| * while interacting with activity UI. | |||||
| */ | |||||
| private val delayHideTouchListener = View.OnTouchListener { view, motionEvent -> | |||||
| when (motionEvent.action) { | |||||
| MotionEvent.ACTION_DOWN -> if (AUTO_HIDE) { | |||||
| delayedHide(AUTO_HIDE_DELAY_MILLIS) | |||||
| } | |||||
| MotionEvent.ACTION_UP -> view.performClick() | |||||
| else -> { | |||||
| } | |||||
| } | |||||
| false | |||||
| } | |||||
| @SuppressLint("ClickableViewAccessibility") | |||||
| override fun onCreate(savedInstanceState: Bundle?) { | |||||
| super.onCreate(savedInstanceState) | |||||
| binding = ActivityFullscreenBinding.inflate(layoutInflater) | |||||
| setContentView(binding.root) | |||||
| supportActionBar?.setDisplayHomeAsUpEnabled(true) | |||||
| isFullscreen = true | |||||
| // Set up the user interaction to manually show or hide the system UI. | |||||
| fullscreenContent = binding.fullscreenContent | |||||
| fullscreenContent.setOnClickListener { toggle() } | |||||
| fullscreenContentControls = binding.fullscreenContentControls | |||||
| // Upon interacting with UI controls, delay any scheduled hide() | |||||
| // operations to prevent the jarring behavior of controls going away | |||||
| // while interacting with the UI. | |||||
| binding.dummyButton.setOnTouchListener(delayHideTouchListener) | |||||
| } | |||||
| override fun onPostCreate(savedInstanceState: Bundle?) { | |||||
| super.onPostCreate(savedInstanceState) | |||||
| // Trigger the initial hide() shortly after the activity has been | |||||
| // created, to briefly hint to the user that UI controls | |||||
| // are available. | |||||
| delayedHide(100) | |||||
| } | |||||
| private fun toggle() { | |||||
| if (isFullscreen) { | |||||
| hide() | |||||
| } else { | |||||
| show() | |||||
| } | |||||
| } | |||||
| private fun hide() { | |||||
| // Hide UI first | |||||
| supportActionBar?.hide() | |||||
| fullscreenContentControls.visibility = View.GONE | |||||
| isFullscreen = false | |||||
| // Schedule a runnable to remove the status and navigation bar after a delay | |||||
| hideHandler.removeCallbacks(showPart2Runnable) | |||||
| hideHandler.postDelayed(hidePart2Runnable, UI_ANIMATION_DELAY.toLong()) | |||||
| } | |||||
| private fun show() { | |||||
| // Show the system bar | |||||
| if (Build.VERSION.SDK_INT >= 30) { | |||||
| fullscreenContent.windowInsetsController?.show(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) | |||||
| } else { | |||||
| fullscreenContent.systemUiVisibility = | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or | |||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | |||||
| } | |||||
| isFullscreen = true | |||||
| // Schedule a runnable to display UI elements after a delay | |||||
| hideHandler.removeCallbacks(hidePart2Runnable) | |||||
| hideHandler.postDelayed(showPart2Runnable, UI_ANIMATION_DELAY.toLong()) | |||||
| } | |||||
| /** | |||||
| * Schedules a call to hide() in [delayMillis], canceling any | |||||
| * previously scheduled calls. | |||||
| */ | |||||
| private fun delayedHide(delayMillis: Int) { | |||||
| hideHandler.removeCallbacks(hideRunnable) | |||||
| hideHandler.postDelayed(hideRunnable, delayMillis.toLong()) | |||||
| } | |||||
| companion object { | |||||
| /** | |||||
| * Whether or not the system UI should be auto-hidden after | |||||
| * [AUTO_HIDE_DELAY_MILLIS] milliseconds. | |||||
| */ | |||||
| private const val AUTO_HIDE = true | |||||
| /** | |||||
| * If [AUTO_HIDE] is set, the number of milliseconds to wait after | |||||
| * user interaction before hiding the system UI. | |||||
| */ | |||||
| private const val AUTO_HIDE_DELAY_MILLIS = 3000 | |||||
| /** | |||||
| * Some older devices needs a small delay between UI widget updates | |||||
| * and a change of the status and navigation bar. | |||||
| */ | |||||
| private const val UI_ANIMATION_DELAY = 300 | |||||
| } | |||||
| } |
| <?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" | |||||
| android:background="?attr/fullscreenBackgroundColor" | |||||
| android:theme="@style/ThemeOverlay.XklLocal.FullscreenContainer" | |||||
| tools:context=".FullscreenActivity"> | |||||
| <!-- The primary full-screen view. This can be replaced with whatever view | |||||
| is needed to present your content, e.g. VideoView, SurfaceView, | |||||
| TextureView, etc. --> | |||||
| <TextView | |||||
| android:id="@+id/fullscreen_content" | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="match_parent" | |||||
| android:gravity="center" | |||||
| android:keepScreenOn="true" | |||||
| android:text="@string/dummy_content" | |||||
| android:textColor="?attr/fullscreenTextColor" | |||||
| android:textSize="50sp" | |||||
| android:textStyle="bold" /> | |||||
| <!-- This FrameLayout insets its children based on system windows using | |||||
| android:fitsSystemWindows. --> | |||||
| <FrameLayout | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="match_parent" | |||||
| android:fitsSystemWindows="true"> | |||||
| <LinearLayout | |||||
| android:id="@+id/fullscreen_content_controls" | |||||
| style="@style/Widget.Theme.XklLocal.ButtonBar.Fullscreen" | |||||
| android:layout_width="match_parent" | |||||
| android:layout_height="wrap_content" | |||||
| android:layout_gravity="bottom|center_horizontal" | |||||
| android:orientation="horizontal" | |||||
| tools:ignore="UselessParent"> | |||||
| <Button | |||||
| android:id="@+id/dummy_button" | |||||
| style="?android:attr/buttonBarButtonStyle" | |||||
| android:layout_width="0dp" | |||||
| android:layout_height="wrap_content" | |||||
| android:layout_weight="1" | |||||
| android:text="@string/dummy_button" /> | |||||
| </LinearLayout> | |||||
| </FrameLayout> | |||||
| </FrameLayout> |
| <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> | <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> | ||||
| <!-- Customize your theme here. --> | <!-- Customize your theme here. --> | ||||
| </style> | </style> | ||||
| <style name="ThemeOverlay.XklLocal.FullscreenContainer" parent=""> | |||||
| <item name="fullscreenBackgroundColor">@color/light_blue_900</item> | |||||
| <item name="fullscreenTextColor">@color/light_blue_A400</item> | |||||
| </style> | |||||
| </resources> | </resources> |
| <string name="app_name">XklLocal</string> | <string name="app_name">XklLocal</string> | ||||
| <string name="dummy_button">Dummy Button</string> | <string name="dummy_button">Dummy Button</string> | ||||
| <string name="dummy_content">DUMMY\nCONTENT</string> | <string name="dummy_content">DUMMY\nCONTENT</string> | ||||
| <!-- TODO: Remove or change this placeholder text --> | |||||
| <string name="hello_blank_fragment">Hello blank fragment</string> | |||||
| </resources> | </resources> |
| <resources> | <resources> | ||||
| <style name="Widget.Theme.XklLocal.ActionBar.Fullscreen" parent="Widget.AppCompat.ActionBar"> | |||||
| <item name="android:background">@color/black_overlay</item> | |||||
| </style> | |||||
| <style name="Widget.Theme.XklLocal.ButtonBar.Fullscreen" parent=""> | |||||
| <item name="android:background">@color/black_overlay</item> | |||||
| <item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item> | |||||
| </style> | |||||
| </resources> | </resources> |
| <!-- Customize your theme here. --> | <!-- Customize your theme here. --> | ||||
| </style> | </style> | ||||
| <style name="Theme.XklLocal.Fullscreen" parent="Theme.XklLocal"> | |||||
| <item name="android:actionBarStyle">@style/Widget.Theme.XklLocal.ActionBar.Fullscreen</item> | |||||
| <item name="android:windowActionBarOverlay">true</item> | |||||
| <item name="android:windowBackground">@null</item> | |||||
| </style> | |||||
| <style name="ThemeOverlay.XklLocal.FullscreenContainer" parent=""> | |||||
| <item name="fullscreenBackgroundColor">@color/light_blue_600</item> | |||||
| <item name="fullscreenTextColor">@color/light_blue_A200</item> | |||||
| </style> | |||||
| </resources> | </resources> |
| //在项目级别定义某些属性并在所有模块之间共享这些属性 | //在项目级别定义某些属性并在所有模块之间共享这些属性 | ||||
| ext { | ext { | ||||
| compile_sdk_version = 30 //使用rootProject.ext.compile_sdk_version | |||||
| android = [ | |||||
| compile_sdk_version: 30, //使用rootProject.ext.android.compile_sdk_version | |||||
| build_tools_version: "30.0.2", | |||||
| min_sdk_version : 21, | |||||
| target_sdk_version : 30, | |||||
| version_code : 100, | |||||
| version_name : "100", | |||||
| applicationId : "com.xkl.cdl" | |||||
| ] | |||||
| versions = [ | |||||
| core_ktx_version : "1.3.2", | |||||
| appcompat_version: "1.2.0", | |||||
| material_version : "1.3.0", | |||||
| ] | |||||
| //必须依赖 | |||||
| dependencies_required = [ | |||||
| //为属于Android框架的通用库提供扩展程序 | |||||
| core_ktx : "androidx.core:core-ktx:${versions.core_ktx_version}", | |||||
| //Androidx 依赖 | |||||
| appcompat: "androidx.appcompat:appcompat:${versions.appcompat_version}", | |||||
| //material_design | |||||
| material : "com.google.android.material:material:${versions.material_version}", | |||||
| ] | |||||
| dependencies_testImplementation = [ | |||||
| junit: "junit:junit:4.+" | |||||
| ] | |||||
| dependencies_androidTestImplementation = [ | |||||
| test_ext_junit : "androidx.test.ext:junit:1.1.2", | |||||
| test_espresson_core: "androidx.test.espresso:espresso-core:3.3.0" | |||||
| ] | |||||
| //按需依赖项 | |||||
| dependencies_custom = [] | |||||
| } | } |
| } | } | ||||
| rootProject.name = "XklLocal" | rootProject.name = "XklLocal" | ||||
| include ':app' | include ':app' | ||||
| include ':lib:common' |