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