使用Anko访问活动的视图
我知道我可以使用Anko的id
属性来识别视图:
class MainActivityUI : AnkoComponent<MainActivity> { override fun createView(ui: AnkoContext<MainActivity>) = with(ui) { frameLayout { textView { id = R.id.text } } } }
然后使用find()
函数(或使用Kotlin Android扩展)在Activity
获取它:
class MainActivity : AppCompatActivity() { private val textView by lazy { find<TextView>(R.id.text) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) MainActivityUI().setContentView(this) textView.text = "Hello World" } }
但我觉得我失去了一些东西; README中唯一提到find
函数或Kotlin Android扩展的地方在标题为支持现有代码的部分:
您不必使用Anko重写所有的用户界面。 你可以保留用Java编写的旧类。 而且,如果您仍然希望(或必须)编写Kotlin活动类并由于某种原因膨胀XML布局,则可以使用“视图”属性,这将使事情变得更加简单:
// Same as findViewById(), simpler to use val name = find<TextView>(R.id.name) name.hint = "Enter your name" name.onClick { /*do something*/ }
通过使用Kotlin Android扩展,您可以使代码更加紧凑。
这使得它看起来像find
功能只是为了支持“旧”的XML代码。
所以我的问题是这个。 正在使用一个id
与find
函数一起使用Anko访问Activity
View
的正确方法? 有更多的“Anko”方式来处理这个? 或者我错过了Anko的一些其他好处,使得从Activity
访问View
不相关?
第二个相关的问题; 如果这是从Activity
中访问View
的正确方法,是否有一种方法可以在AnkoComponent
中创建一个id
资源(即"@+id/"
)? 而不是在ids.xml
文件中创建每个id
。
那么,为什么仍然使用XML id
来定位View呢? 因为我们已经使用了Anko而不是XML。
在我看来,我们可以将视图元素存储在AnkoComponent
而不是find view
的id方法。 检查代码打击:
class MainActivityUI : AnkoComponent<MainActivity> { lateinit var txtView: TextView override fun createView(ui: AnkoContext<MainActivity>) = with(ui) { frameLayout { txtView = textView { id = R.id.text // the id here is useless, we can delete this line. } } } } class MainActivity : AppCompatActivity() { lateinit var mainUI : MainActivityUI override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mainUI = MainActivityUI() mainUI.setContentView(this) mainUI.txtView.text = "Hello World" } }
我相信,因为您可以将行为添加到您的Anko文件中,所以您不必在活动中实例化您的视图。
这可能非常酷,因为你可以更多地分离视图层。 所有在您的视图中的代码都可以插入到Anko文件中。 所以你所要做的就是从Anko调用你的活动的方法,而不是实例化任何视图。
但是,如果您需要实例化任何视图…您可以在您的活动中使用Kotlin Android扩展。
例:
代码在您的活动:
seekBar.setOnSeekBarChangeListener(object: OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { // Something } override fun onStartTrackingTouch(seekBar: SeekBar?) { // Just an empty method } override fun onStopTrackingTouch(seekBar: SeekBar) { // Another empty method } })
代码在Anko:
seekBar { onSeekBarChangeListener { onProgressChanged { seekBar, progress, fromUser -> // Something } } }
现在代码在AnkoComponent中。 不需要实例化视图。
结论:
如果你把所有的视图逻辑放到AnkoComponents中,而不是在你的活动中,那么这是一个更“Anko”的编程方式。
编辑:
作为一个代码的例子,你不必实例化一个视图:
在你的Anko:
var networkFeedback : TextView = null override fun createView(ui: AnkoContext<MainActivity>) = with(ui) { frameLayout { textView { id = R.id.text2 networkFeedback = this onClick { ui.owner.doSomething(2, this) } } } } fun networkFeedback(text: String){ networkFeedback.text = text }
在你的活动中:
class MainActivity : AppCompatActivity() { overriding fun onCreate{ [...] val mainUi = AnkoUi() // some dynamic task... mainUi.networkFeedback("lalala") } fun doSomething(number: Int, callback: TextView){ //Some network or database task goes here! //And then, if the operation was successful callback.text = "Something has changed..." }
这是一个非常不同的方法。 我不太确定,如果我喜欢或不喜欢,但这是一个完全不同的讨论…
不要使用ID来识别与Anko DSL的意见! 这是没有必要的,因为Anko是为了摆脱XML布局而设计的。 而是使用这种模式:
class ActivityMain : AppCompatActivity() { var mTextView: TextView // put it here to be accessible everywhere override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ActivityMainUI().setContentView(this) } fun yourClassMethod() { // So this is am example how to get the textView // defined in your Anko DSL class (not by id!): mTextView.text = "bla-bla-bla" } } class ActivityMainUI : AnkoComponent<ActivityMain> { override fun createView(ui: AnkoContext<ActivityMain>) = with(ui) { // your fancy interface with Anko DSL: verticalLayout { owner.mTextView = textView } } }
请注意UI类的定义:
class ActivityMainUI : AnkoComponent<ActivityMain> {
如果你把活动类的名字放在方括号中,那么所有的公共变量都可以通过UI类的主体来访问,所以你可以在那里指定它们。
但是你可以很容易地把AppCompatActivity ,并使一些可能被克隆的通用类。 在这种情况下,使用lateinit var mTextView:TextView在UI类的主体中,如Jacob的答案中所述。
- android.R.id视图绑定在Kotlin
- Kotlin为Android和静态最终的内部类
- Android选择和取消选择适配器kotlin中的项目的问题?
- Kotlin和惯用的方式来写,'如果不是空的,否则…'基于可变值
- Haskell中的HasSupportFragmentInjector问题 – DispatchingAndroidInjector为null
- 如何将ByteArray转换为Kotlin中指定字符集的字符串
- 如何在Android中使用kotlin获取片段中的资源ID?
- 以编程方式使用变量使imageView可见/不可见
- 在使用kotlin时,使用实体和Dao文件的正式/正确的方式是什么?