diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..b589d56
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..0039db1
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..fdf8d99
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e837843
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 1f939cc..358d444 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -40,12 +40,14 @@ android {
dependencies {
+
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
implementation("androidx.navigation:navigation-ui-ktx:2.5.3")
+ implementation(project(mapOf("path" to ":scalableLayout")))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
diff --git a/app/src/main/java/com/coldmint/scalableLayout/FirstFragment.kt b/app/src/main/java/com/coldmint/scalableLayout/FirstFragment.kt
deleted file mode 100644
index 476e4d4..0000000
--- a/app/src/main/java/com/coldmint/scalableLayout/FirstFragment.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.coldmint.scalableLayout
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.navigation.fragment.findNavController
-import com.coldmint.scalableLayout.databinding.FragmentFirstBinding
-
-/**
- * A simple [Fragment] subclass as the default destination in the navigation.
- */
-class FirstFragment : Fragment() {
-
- private var _binding: FragmentFirstBinding? = null
-
- // This property is only valid between onCreateView and
- // onDestroyView.
- private val binding get() = _binding!!
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
-
- _binding = FragmentFirstBinding.inflate(inflater, container, false)
- return binding.root
-
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- binding.buttonFirst.setOnClickListener {
- findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
- }
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/coldmint/scalableLayout/MainActivity.kt b/app/src/main/java/com/coldmint/scalableLayout/MainActivity.kt
index 538e6a7..c078894 100644
--- a/app/src/main/java/com/coldmint/scalableLayout/MainActivity.kt
+++ b/app/src/main/java/com/coldmint/scalableLayout/MainActivity.kt
@@ -13,7 +13,6 @@ import com.coldmint.scalableLayout.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
- private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
@@ -24,35 +23,6 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(binding.toolbar)
- val navController = findNavController(R.id.nav_host_fragment_content_main)
- appBarConfiguration = AppBarConfiguration(navController.graph)
- setupActionBarWithNavController(navController, appBarConfiguration)
-
- binding.fab.setOnClickListener { view ->
- Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
- .setAction("Action", null).show()
- }
}
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- // Inflate the menu; this adds items to the action bar if it is present.
- menuInflater.inflate(R.menu.menu_main, menu)
- return true
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- return when (item.itemId) {
- R.id.action_settings -> true
- else -> super.onOptionsItemSelected(item)
- }
- }
-
- override fun onSupportNavigateUp(): Boolean {
- val navController = findNavController(R.id.nav_host_fragment_content_main)
- return navController.navigateUp(appBarConfiguration)
- || super.onSupportNavigateUp()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/coldmint/scalableLayout/SecondFragment.kt b/app/src/main/java/com/coldmint/scalableLayout/SecondFragment.kt
deleted file mode 100644
index f99dc95..0000000
--- a/app/src/main/java/com/coldmint/scalableLayout/SecondFragment.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.coldmint.scalableLayout
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.navigation.fragment.findNavController
-import com.coldmint.scalableLayout.databinding.FragmentSecondBinding
-
-/**
- * A simple [Fragment] subclass as the second destination in the navigation.
- */
-class SecondFragment : Fragment() {
-
- private var _binding: FragmentSecondBinding? = null
-
- // This property is only valid between onCreateView and
- // onDestroyView.
- private val binding get() = _binding!!
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
-
- _binding = FragmentSecondBinding.inflate(inflater, container, false)
- return binding.root
-
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- binding.buttonSecond.setOnClickListener {
- findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
- }
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 16313e0..1aaa61c 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -19,15 +19,48 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
deleted file mode 100644
index e416e1c..0000000
--- a/app/src/main/res/layout/content_main.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_first.xml b/app/src/main/res/layout/fragment_first.xml
deleted file mode 100644
index 44baecd..0000000
--- a/app/src/main/res/layout/fragment_first.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_second.xml b/app/src/main/res/layout/fragment_second.xml
deleted file mode 100644
index d074310..0000000
--- a/app/src/main/res/layout/fragment_second.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
deleted file mode 100644
index cc744fa..0000000
--- a/app/src/main/res/menu/menu_main.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
deleted file mode 100644
index 3aa4752..0000000
--- a/app/src/main/res/navigation/nav_graph.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 1bc1d16..eb282f1 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,4 +2,5 @@
plugins {
id("com.android.application") version "8.1.3" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
+ id("com.android.library") version "8.1.3" apply false
}
\ No newline at end of file
diff --git a/scalableLayout/.gitignore b/scalableLayout/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/scalableLayout/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/scalableLayout/build.gradle.kts b/scalableLayout/build.gradle.kts
new file mode 100644
index 0000000..90cd653
--- /dev/null
+++ b/scalableLayout/build.gradle.kts
@@ -0,0 +1,43 @@
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+}
+
+android {
+ namespace = "com.coldmint.scalablelayout"
+ compileSdk = 33
+
+ defaultConfig {
+ minSdk = 24
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles("consumer-rules.pro")
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+dependencies {
+
+ implementation("androidx.core:core-ktx:1.9.0")
+ implementation("androidx.appcompat:appcompat:1.6.1")
+ implementation("com.google.android.material:material:1.8.0")
+ testImplementation("junit:junit:4.13.2")
+ androidTestImplementation("androidx.test.ext:junit:1.1.5")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
+}
\ No newline at end of file
diff --git a/scalableLayout/consumer-rules.pro b/scalableLayout/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/scalableLayout/proguard-rules.pro b/scalableLayout/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/scalableLayout/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/scalableLayout/src/androidTest/java/com/coldmint/scalablelayout/ExampleInstrumentedTest.kt b/scalableLayout/src/androidTest/java/com/coldmint/scalablelayout/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..f385afe
--- /dev/null
+++ b/scalableLayout/src/androidTest/java/com/coldmint/scalablelayout/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.coldmint.scalablelayout
+
+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.coldmint.scalablelayout.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/scalableLayout/src/main/AndroidManifest.xml b/scalableLayout/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/scalableLayout/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/scalableLayout/src/main/java/com/coldmint/scalablelayout/OnWidthChangeListener.kt b/scalableLayout/src/main/java/com/coldmint/scalablelayout/OnWidthChangeListener.kt
new file mode 100644
index 0000000..8b19487
--- /dev/null
+++ b/scalableLayout/src/main/java/com/coldmint/scalablelayout/OnWidthChangeListener.kt
@@ -0,0 +1,12 @@
+package com.coldmint.scalablelayout
+
+interface OnWidthChangeListener {
+ /**
+ * 当宽度改变时
+ *
+ * @param newWidth 新宽度
+ * @param minWidth 最小宽度
+ * @param maxWidth 最大宽度
+ */
+ fun onChange(newWidth: Int, minWidth: Int, maxWidth: Int)
+}
\ No newline at end of file
diff --git a/scalableLayout/src/main/java/com/coldmint/scalablelayout/ScalableLayout.kt b/scalableLayout/src/main/java/com/coldmint/scalablelayout/ScalableLayout.kt
new file mode 100644
index 0000000..759768a
--- /dev/null
+++ b/scalableLayout/src/main/java/com/coldmint/scalablelayout/ScalableLayout.kt
@@ -0,0 +1,92 @@
+package com.coldmint.scalablelayout
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.widget.LinearLayout
+
+class ScalableLayout : LinearLayout {
+
+
+ //最小宽度
+ var minWidth = 0
+
+ //最大宽度
+ var maxWidth = Int.MAX_VALUE
+
+ private var startX = 0f
+ private var onWidthChangeListener: OnWidthChangeListener? = null
+
+ constructor(context: Context?) : super(context)
+
+ constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
+ init(attrs)
+ }
+
+ constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
+ context,
+ attrs,
+ defStyleAttr
+ ) {
+ init(attrs)
+ }
+
+ constructor(
+ context: Context?,
+ attrs: AttributeSet?,
+ defStyleAttr: Int,
+ defStyleRes: Int
+ ) : super(context, attrs, defStyleAttr, defStyleRes) {
+ init(attrs)
+ }
+
+ private fun init(attrs: AttributeSet?) {
+ val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScalableLayout)
+ minWidth = typedArray.getDimensionPixelSize(R.styleable.ScalableLayout_android_minWidth, 0)
+ maxWidth = typedArray.getDimensionPixelSize(
+ R.styleable.ScalableLayout_android_maxWidth,
+ Int.MAX_VALUE
+ )
+ typedArray.recycle()
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val widthSize = MeasureSpec.getSize(widthMeasureSpec)
+ val widthMode = MeasureSpec.getMode(widthMeasureSpec)
+ var newWidth = widthSize
+ if (widthMode == MeasureSpec.AT_MOST) {
+ newWidth = widthSize.coerceAtMost(maxWidth)
+ newWidth = newWidth.coerceAtLeast(minWidth)
+ } else if (widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.EXACTLY) {
+ newWidth = newWidth.coerceAtLeast(minWidth)
+ newWidth = newWidth.coerceAtMost(maxWidth)
+ }
+ val newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, widthMode)
+ super.onMeasure(newWidthMeasureSpec, heightMeasureSpec)
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> startX = event.rawX
+ MotionEvent.ACTION_MOVE -> {
+ val offsetX = event.rawX - startX
+ var newWidth = width + offsetX.toInt()
+ newWidth = minWidth.coerceAtLeast(newWidth)
+ newWidth = maxWidth.coerceAtMost(newWidth)
+ if (onWidthChangeListener != null) {
+ onWidthChangeListener!!.onChange(newWidth, minWidth, maxWidth)
+ }
+ val layoutParams = layoutParams
+ layoutParams.width = newWidth
+ setLayoutParams(layoutParams)
+ startX = event.rawX
+ }
+
+ MotionEvent.ACTION_UP -> {}
+ }
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/scalableLayout/src/main/res/values/attrs.xml b/scalableLayout/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..34e4518
--- /dev/null
+++ b/scalableLayout/src/main/res/values/attrs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scalableLayout/src/test/java/com/coldmint/scalablelayout/ExampleUnitTest.kt b/scalableLayout/src/test/java/com/coldmint/scalablelayout/ExampleUnitTest.kt
new file mode 100644
index 0000000..b2d0b03
--- /dev/null
+++ b/scalableLayout/src/test/java/com/coldmint/scalablelayout/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.coldmint.scalablelayout
+
+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/settings.gradle.kts b/settings.gradle.kts
index 13f5325..dd01ae1 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -23,4 +23,4 @@ dependencyResolutionManagement {
rootProject.name = "ScalableLayout"
include(":app")
-
\ No newline at end of file
+include(":scalableLayout")