mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Test all attribute adapters
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
<AbsoluteLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/template_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
+6
-4
@@ -43,8 +43,10 @@ import com.itsaky.androidide.inflater.internal.utils.IDTable
|
||||
import com.itsaky.androidide.projects.ProjectManager
|
||||
import com.itsaky.androidide.projects.api.AndroidModule
|
||||
import com.itsaky.androidide.utils.ILogger
|
||||
import com.itsaky.androidide.utils.VMUtils
|
||||
import com.itsaky.androidide.xml.widgets.Widget
|
||||
import com.itsaky.androidide.xml.widgets.WidgetTable
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
|
||||
@@ -64,7 +66,7 @@ open class LayoutInflaterImpl : ILayoutInflater() {
|
||||
get() = this._primaryInflatingFile!!
|
||||
|
||||
protected val currentLayoutFile: LayoutFile
|
||||
get() = _currentLayoutFile!!
|
||||
get() = this._currentLayoutFile!!
|
||||
|
||||
override fun inflate(file: File, parent: ViewGroup): IView? {
|
||||
this._primaryInflatingFile = file
|
||||
@@ -167,11 +169,11 @@ open class LayoutInflaterImpl : ILayoutInflater() {
|
||||
val adapter =
|
||||
AttributeAdapterIndex.getAdapter(view.name)
|
||||
?: throw InflateException("No attribute adapter found for view ${view.name}")
|
||||
|
||||
adapter.applyBasic(view)
|
||||
|
||||
|
||||
view.view.layoutParams = generateLayoutParams(parentView)
|
||||
parent.addChild(view)
|
||||
|
||||
adapter.applyBasic(view)
|
||||
|
||||
if (element.childCount > 0 && view is IViewGroup) {
|
||||
for (child in element.childList) {
|
||||
|
||||
@@ -35,7 +35,7 @@ constructor(
|
||||
override val tag: String = name.tagName()
|
||||
) : IView {
|
||||
private val log = ILogger.newInstance(javaClass.simpleName)
|
||||
protected val attributes = mutableListOf<IAttribute>()
|
||||
internal val attributes = mutableListOf<IAttribute>()
|
||||
|
||||
override var parent: IViewGroup? = null
|
||||
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ open class ViewAttrAdapter : IAttributeAdapter() {
|
||||
"foregroundGravity" -> foregroundGravity = parseGravity(value)
|
||||
"foregroundTint" -> foregroundTintList = parseColorStateList(context, value)
|
||||
"foregroundTintMode" -> foregroundTintMode = parsePorterDuffMode(value)
|
||||
"id" -> parseId(file.resName, value)
|
||||
"id" -> id = parseId(file.resName, value)
|
||||
"minHeight" -> minimumWidth = parseDimension(context, value)
|
||||
"minWidth" -> minimumHeight = parseDimension(context, value)
|
||||
"padding" ->
|
||||
|
||||
@@ -51,59 +51,21 @@ import com.itsaky.androidide.inflater.internal.adapters.WebViewAttrAdapter
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import java.io.File
|
||||
|
||||
/** @author Akash Yadav */
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class AdapterIndexText {
|
||||
|
||||
|
||||
@Test
|
||||
fun `verify instances of adapters`() {
|
||||
val expected =
|
||||
mapOf(
|
||||
AbsoluteLayout::class to AbsoluteLayoutAttrAdapter::class,
|
||||
AutoCompleteTextView::class to AutoCompleteTextViewAttrAdapter::class,
|
||||
Button::class to ButtonAttrAdapter::class,
|
||||
CheckBox::class to CheckBoxAttrAdapter::class,
|
||||
CheckedTextView::class to CheckedTextViewAttrAdapter::class,
|
||||
EditText::class to EditTextAttrAdapter::class,
|
||||
FrameLayout::class to FrameLayoutAttrAdapter::class,
|
||||
GestureOverlayView::class to GestureOverlayViewAttrAdapter::class,
|
||||
GridLayout::class to GridLayoutAttrAdapter::class,
|
||||
ImageButton::class to ImageButtonAttrAdapter::class,
|
||||
ImageView::class to ImageViewAttrAdapter::class,
|
||||
LinearLayout::class to LinearLayoutAttrAdapter::class,
|
||||
ListView::class to ListViewAttrAdapter::class,
|
||||
ProgressBar::class to ProgressBarAttrAdapter::class,
|
||||
RadioButton::class to RadioButtonAttrAdapter::class,
|
||||
RelativeLayout::class to RelativeLayoutAttrAdapter::class,
|
||||
SeekBar::class to SeekBarAttrAdapter::class,
|
||||
Spinner::class to SpinnerAttrAdapter::class,
|
||||
Switch::class to SwitchAttrAdapter::class,
|
||||
SurfaceView::class to SurfaceViewAttrAdapter::class,
|
||||
TextView::class to TextViewAttrAdapter::class,
|
||||
TextureView::class to TextureViewAttrAdapter::class,
|
||||
ToggleButton::class to ToggleButtonAttrAdapter::class,
|
||||
View::class to ViewAttrAdapter::class,
|
||||
WebView::class to WebViewAttrAdapter::class
|
||||
)
|
||||
|
||||
val unexpected =
|
||||
listOf(
|
||||
AbsListView::class,
|
||||
AbsSeekBar::class,
|
||||
AbsSpinner::class,
|
||||
AdapterView::class,
|
||||
CompoundButton::class,
|
||||
ViewGroup::class
|
||||
)
|
||||
|
||||
expected.forEach {
|
||||
viewToAdapter.forEach {
|
||||
AttributeAdapterIndex.getAdapter(it.key.qualifiedName).apply {
|
||||
assertThat(this).isNotNull()
|
||||
assertThat(this).isInstanceOf(it.value.java)
|
||||
}
|
||||
}
|
||||
|
||||
unexpected.forEach { assertThat(AttributeAdapterIndex.getAdapter(it.qualifiedName)).isNull() }
|
||||
abstractViews.forEach { assertThat(AttributeAdapterIndex.getAdapter(it.qualifiedName)).isNull() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,22 @@ package com.itsaky.androidide.inflater
|
||||
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.itsaky.androidide.lookup.Lookup
|
||||
import com.itsaky.androidide.inflater.internal.AttributeImpl
|
||||
import com.itsaky.androidide.inflater.internal.LayoutInflaterImpl
|
||||
import com.itsaky.androidide.inflater.internal.ViewImpl
|
||||
import com.itsaky.androidide.inflater.internal.utils.IDTable
|
||||
import com.itsaky.androidide.projects.ProjectManager
|
||||
import com.itsaky.androidide.projects.builder.BuildService
|
||||
import com.itsaky.androidide.tooling.api.messages.InitializeProjectMessage
|
||||
import com.itsaky.androidide.tooling.testing.ToolingApiTestLauncher
|
||||
import com.itsaky.androidide.projects.api.AndroidModule
|
||||
import java.io.File
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.android.controller.ActivityController
|
||||
|
||||
/** @author Akash Yadav */
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class LayoutInflaterTest {
|
||||
|
||||
|
||||
@Test
|
||||
fun `test functionality`() {
|
||||
inflaterTest {
|
||||
@@ -53,7 +50,7 @@ class LayoutInflaterTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `test inlined layout`() {
|
||||
inflaterTest {
|
||||
@@ -70,8 +67,46 @@ class LayoutInflaterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test inflated view is of expected type`() {
|
||||
inflaterTest { module ->
|
||||
requiresActivity { activity ->
|
||||
val parent = LinearLayout(activity)
|
||||
val inflater = ILayoutInflater.newInflater() as LayoutInflaterImpl
|
||||
viewToAdapter.keys.forEach { view ->
|
||||
parent.removeAllViews()
|
||||
module.createLayoutFile(view.simpleName!!) { file ->
|
||||
file.writeText(viewDeclTemplate(view.simpleName!!))
|
||||
val inflated = inflater.inflate(file, parent)
|
||||
assertThat(inflated!!.view).isInstanceOf(view.java)
|
||||
assertThat(inflated.view.id)
|
||||
.isEqualTo(IDTable.get(view.simpleName!!, "template_view"))
|
||||
|
||||
(inflated as ViewImpl).attributes.apply {
|
||||
assertThat(this)
|
||||
.contains(AttributeImpl(INamespace.ANDROID, "id", "@+id/template_view"))
|
||||
assertThat(this)
|
||||
.contains(AttributeImpl(INamespace.ANDROID, "layout_height", "match_parent"))
|
||||
assertThat(this)
|
||||
.contains(AttributeImpl(INamespace.ANDROID, "layout_width", "match_parent"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun layoutFile(name: String): File {
|
||||
val app = ProjectManager.app ?: throw IllegalStateException("Project is not initialized")
|
||||
return File(app.projectDir, "src/main/res/layout/$name.xml")
|
||||
}
|
||||
|
||||
private fun AndroidModule.createLayoutFile(name: String, block: (File) -> Unit = {}): File {
|
||||
return File(projectDir, "src/main/res/layout/$name.xml").apply {
|
||||
if (exists()) {
|
||||
delete()
|
||||
}
|
||||
block(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.inflater
|
||||
|
||||
import android.gesture.GestureOverlayView
|
||||
import android.view.SurfaceView
|
||||
import android.view.TextureView
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.WebView
|
||||
import android.widget.AbsListView
|
||||
import android.widget.AbsSeekBar
|
||||
import android.widget.AbsSpinner
|
||||
import android.widget.AbsoluteLayout
|
||||
import android.widget.AdapterView
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.Button
|
||||
import android.widget.CheckBox
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.GridLayout
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ListView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Spinner
|
||||
import android.widget.Switch
|
||||
import android.widget.TextView
|
||||
import android.widget.ToggleButton
|
||||
import com.itsaky.androidide.inflater.internal.adapters.AbsoluteLayoutAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.AutoCompleteTextViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ButtonAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.CheckBoxAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.CheckedTextViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.EditTextAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.FrameLayoutAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.GestureOverlayViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.GridLayoutAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ImageButtonAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ImageViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.LinearLayoutAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ListViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ProgressBarAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.RadioButtonAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.RelativeLayoutAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.SeekBarAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.SpinnerAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.SurfaceViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.SwitchAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.TextViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.TextureViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ToggleButtonAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.ViewAttrAdapter
|
||||
import com.itsaky.androidide.inflater.internal.adapters.WebViewAttrAdapter
|
||||
|
||||
internal fun viewDeclTemplate(name: String) : String =
|
||||
"""
|
||||
<$name
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/template_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
""".trimIndent()
|
||||
|
||||
internal val viewToAdapter =
|
||||
mapOf(
|
||||
AbsoluteLayout::class to AbsoluteLayoutAttrAdapter::class,
|
||||
AutoCompleteTextView::class to AutoCompleteTextViewAttrAdapter::class,
|
||||
Button::class to ButtonAttrAdapter::class,
|
||||
CheckBox::class to CheckBoxAttrAdapter::class,
|
||||
CheckedTextView::class to CheckedTextViewAttrAdapter::class,
|
||||
EditText::class to EditTextAttrAdapter::class,
|
||||
FrameLayout::class to FrameLayoutAttrAdapter::class,
|
||||
GestureOverlayView::class to GestureOverlayViewAttrAdapter::class,
|
||||
GridLayout::class to GridLayoutAttrAdapter::class,
|
||||
ImageButton::class to ImageButtonAttrAdapter::class,
|
||||
ImageView::class to ImageViewAttrAdapter::class,
|
||||
LinearLayout::class to LinearLayoutAttrAdapter::class,
|
||||
ListView::class to ListViewAttrAdapter::class,
|
||||
ProgressBar::class to ProgressBarAttrAdapter::class,
|
||||
RadioButton::class to RadioButtonAttrAdapter::class,
|
||||
RelativeLayout::class to RelativeLayoutAttrAdapter::class,
|
||||
SeekBar::class to SeekBarAttrAdapter::class,
|
||||
Spinner::class to SpinnerAttrAdapter::class,
|
||||
Switch::class to SwitchAttrAdapter::class,
|
||||
SurfaceView::class to SurfaceViewAttrAdapter::class,
|
||||
TextView::class to TextViewAttrAdapter::class,
|
||||
TextureView::class to TextureViewAttrAdapter::class,
|
||||
ToggleButton::class to ToggleButtonAttrAdapter::class,
|
||||
View::class to ViewAttrAdapter::class,
|
||||
WebView::class to WebViewAttrAdapter::class
|
||||
)
|
||||
|
||||
internal val abstractViews =
|
||||
listOf(
|
||||
AbsListView::class,
|
||||
AbsSeekBar::class,
|
||||
AbsSpinner::class,
|
||||
AdapterView::class,
|
||||
CompoundButton::class,
|
||||
ViewGroup::class
|
||||
)
|
||||
Reference in New Issue
Block a user