So I completed the first lesson of the Kotlin Course by Google on Udacity and after that I went on to make my own changes to the app that make them look better (just to learn, I don't care about the app). I made some changes like adding dark mode and customizing the UI.
I want the dark mode menu to work properly, like when I click on light mode it should recreate the activity with light mode enabled and should also check the light mode MenutItem. I also want the app to remember the settings so that if I choose Follow System during one session of the app and then close the app, it should keep following the system even after opening the app. I figured this should be done with SharedPreferences but I don't know how to properly do it. As you can see in the video attached below, when I click on any of the dark mode settings options, they don't automatically change the settings, I need to restart the app and only then do I see any changes in the activity that matches to whatever option I selected before closing the app.
Note: I want to mention that I am not very experienced with Android Development or Kotlin, I only started learning 2 months ago. I also want to mention that I DO NOT care about the app itself but I am rather using this app to learn how to get things done. I don't care if my app gets every feature I
would want it to have if I don't also learn how to do those things. It's not the app but the knowledge that I am getting from it that I care about, this is to say that please if you have an answer, do explain how that works.
This video shows the behavior of the app: https://drive.google.com/file/d/1SnN0r351OGF4xQNCtI1wtgouSFVROKzg/view?usp=sharing
I added a toolbar to my layout file of the main (and the only) activity. Here's the xml code for the layout resource:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/diceRollerActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/activity_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:title="#string/app_name" />
</com.google.android.material.appbar.AppBarLayout>
<ImageView
android:id="#+id/dice_image"
android:layout_width="275dp"
android:layout_height="335dp"
android:contentDescription="#+id/diceImage_imageView_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.395"
app:srcCompat="#drawable/empty_dice" />
<Button
android:id="#+id/roll_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="#dimen/Container_Button_Padding"
android:text="#string/roll"
android:textAlignment="center"
android:textAllCaps="false"
android:textColor="#color/white"
android:textSize="25sp"
app:backgroundTint="#color/bold_button_color"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/dice_image"
app:layout_constraintVertical_bias="0.32"
app:rippleColor="#color/button_ripple" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here is my the Kotlin code for the same activity:
package com.example.diceroller
import android.content.Context
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.*
import androidx.appcompat.app.AppCompatDelegate
class MainActivity : AppCompatActivity() {
lateinit var diceImage: ImageView
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.activity_toolbar))
val rollButton: Button = findViewById(R.id.roll_button)
diceImage = findViewById(R.id.dice_image)
rollButton.setOnClickListener {
rollDice()
}
sharedPreferences = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE)
when (sharedPreferences.getString("Night_Mode_State", getString(R.string.follow_system))) {
getString(R.string.follow_system) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
getString(R.string.light_mode) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
getString(R.string.dark_mode) -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.actionbar, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.follow_system -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.follow_system)).apply()
R.id.light_mode -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.light_mode)).apply()
R.id.dark_mode -> sharedPreferences.edit().putString("Night_Mode_State", getString(R.string.dark_mode)).apply()
}
return true
}
private fun rollDice() {
when ((1..6).random()) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
else -> diceImage.setImageResource(R.drawable.dice_6)
}
}
}
This gist includes other files that I think are required to answer this question properly, namely: The menu resource file, the colors resource file and the styles resource file: https://gist.github.com/sbeve72/36a71919f1f965c5dcd466db1e099b4f.js"
Related
I'm a beginner in MVVM and I tried this tutorial. Created a lot of files and pasted the codes but my views aren't recognized. My QuotesActivity.kt file:
package my.mvvm.ui.quotes
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import my.mvvm.R
import my.mvvm.data.Quote
import my.mvvm.utilities.InjectorUtils
class QuotesActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quotes)
initializeUi()
}
private fun initializeUi() {
// Get the QuotesViewModelFactory with all of it's dependencies constructed
val factory = InjectorUtils.provideQuotesViewModelFactory()
// Use ViewModelProviders class to create / get already created QuotesViewModel
// for this view (activity)
val viewModel = ViewModelProviders.of(this, factory)
.get(QuotesViewModel::class.java)
// Observing LiveData from the QuotesViewModel which in turn observes
// LiveData from the repository, which observes LiveData from the DAO ☺
viewModel.getQuotes().observe(this, Observer { quotes ->
val stringBuilder = StringBuilder()
quotes.forEach { quote ->
stringBuilder.append("$quote\n\n")
}
textView_quotes.text = stringBuilder.toString()
})
// When button is clicked, instantiate a Quote and add it to DB through the ViewModel
button_add_quote.setOnClickListener {
val quote = Quote(editText_quote.text.toString(), editText_author.text.toString())
viewModel.addQuote(quote)
editText_quote.setText("")
binding.editText_author.setText("")
}
}
}
Any ideas why this happens? Already tried with two examples and I had the same issue. Thanks.
Edit:
import com.resocoder.mvvmbasicstut.data.Quote
import com.resocoder.mvvmbasicstut.databinding.ActivityQuotesBinding
import com.resocoder.mvvmbasicstut.utilities.InjectorUtils
//import kotlinx.android.synthetic.main.activity_quotes.*
class QuotesActivity : AppCompatActivity() {
lateinit var binding: ActivityQuotesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityQuotesBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.quotes.QuotesActivity">
<TextView
android:id="#+id/textView_quotes"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintHeight_percent="0.55"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:scrollbars="vertical"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
tools:text="I like pineapples. - Thomas Jefferson"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<EditText
android:id="#+id/editText_quote"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.7"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:hint="Quote"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView_quotes"
app:layout_constraintVertical_bias="0.0" />
<EditText
android:id="#+id/editText_author"
android:layout_width="0dp"
app:layout_constraintWidth_percent="0.7"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:hint="Author"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editText_quote"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/button_add_quote"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:backgroundTint="?colorAccent"
android:text="Add Quote"
android:textColor="#android:color/white"
app:layout_constraintBottom_toBottomOf="#+id/editText_author"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="#+id/editText_quote"
app:layout_constraintTop_toTopOf="#+id/editText_quote"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintWidth_percent="0.25" />
</androidx.constraintlayout.widget.ConstraintLayout>
I just edit project from github. You can find it here
The answer to 'Look at my edited question' in Laba Diena's 'Edit:' above of wanting to use View Binding instead of the Kotlin Android Extension with synthetic view bindings is fairly straight forward. There are only two project files that need changing, namely:
(1) 'build.gradle (Module)' and
(2) 'QuotesActivity.kt'
Note: The other project files from the MVVM tutorial can be used 'as is'.
Just make sure that your own 'package name' is at the top of these files.
Project Structure:
(1) build.gradle file:
a) Make this change to the 'plugins' section:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android-extensions' // Delete this line
}
b) Add this entry to the 'android' section:
android {
...
buildFeatures {
viewBinding true
}
}
c) Add this lifecycle option to the 'dependencies' section:
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
(2) QuotesActivity.kt:
Make the necessary changes to the 'QuotesActivity.kt' file as outlined below:
IMPORTANT: When this project is built, it generates a Java file with the necessary databindings for this activity file. It will contain new names that you will have to use with the 'binding' variable in place of the xml attribute names that were previously used. For example, 'button_add_quote' now becomes 'buttonAddQuote', etc. See excerpt below showing the other new names:
public final Button buttonAddQuote; // button_add_quote
public final EditText editTextAuthor; // editText_author
public final EditText editTextQuote; // editText_quote
public final TextView textViewQuotes; // textView_quotes
All these new names can be found in a file called 'ActivityQuotesBinding.java' which is located in the project folder:
'app/build/generated/data_binding_base_class_source_out/debug/out/com/example/mvvmcrashcourse/databinding/'
In the above path, the package name used for this particular project is "com.example.mvvmcrashcourse". Substitute it with your package name.
Finally, this solution works and was tested with Android Studio Bumblebee. If you have problems with build errors, try the following menu options:
Build -> Clean Project
Build -> Rebuild Project
File -> Invalidate Caches
to sum up I am trying to change the src of ImageButtons inside my dialog_colors.xml file from MainActivity. However whatever I do I couldnt manage to change it. I tried the same code with ImageButtons inside my activity_main.xml but it doesnt work for buttons inside dialog_colors.xml file.
activity_main.xlm
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<include
android:id="#+id/dialog_colors"
layout="#layout/dialog_colors"/> ...
dialog_colors.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="#+id/ll_paint_colors"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="#+id/red"
android:layout_width="40sp"
android:layout_height="40sp"
android:src="#drawable/pallet_normal"
android:background="#color/Red"
android:layout_margin="1sp"
android:tag="redTag"
android:clickable="true"
android:onClick="selectColor"
/>...
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
colorDialog=findViewById<LinearLayout>(R.id.dialog_colors)
firstRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors)
secondRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors2)
drawingView=findViewById<DrawingView>(R.id.drawingView)
pressedColor=secondRowColors[0] as ImageButton
pressedColor!!.setImageResource(R.drawable.pallet_pressed)
}...
I tried the same thing with TextViews etc too. It seems like I cannot change anything inside the dialog_colors.xml file.
Do not get confused about the firstRows, secondRows etc, there are many ImageButtons, it doesnt work for any of them.
I found a solution to define an attribute in the MainActivity.kt through activity_main.xml to content_main.xml (included layout). The key word here is DataBinding. The project is completely reproducible and I provide first Kotlin and at the very end the JAVA files.
KOTLIN:
To enable DataBinding you need to go to your build.gradle(Module) and add following code:
//...
dataBinding{
enabled true
}
//...
You define a container called DrawableContainer as a Kotlin class. There you define a Drawable called customDrawable.
Thus DrawableContainer.kt:
import android.graphics.drawable.Drawable
data class DrawableContainer(val customDrawable: Drawable)
Now we will define our MainActivity.kt which will bind our chosen Drawable and pass it through our Container (DrawableContainer).
Our MainActivity.kt:
import android.app.Activity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.imagebuttonexperiment.databinding.ActivityMainBinding
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
binding.drawable = DrawableContainer(resources.getDrawable(R.drawable.my_image))
}
}
The missing parts are our XML files. The code below shows our content_main.xml. It contains a variable (in <data>) we will define named drawable. The type guides to our DrawableContainer. So this is the first bridge between our Container and our layout we will <include. In the ImageButton you can see that as android:src we refer over our variable to our Drawable in our Container. That's why android:src="#{drawable.customDrawable}".
Thus content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="drawable"
type="com.example.imagebuttonexperiment.DrawableContainer" />
</data>
<ImageButton
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="10dp"
android:src="#{drawable.customDrawable}"/>
</layout>
Now it's important to build our second bridge. Yet, we have DrawableContainer -> content_main. This will be the bridge content_main -> MainActivity. Therefor we have our <data/> and variable defined again. As you can see in <include we bind:drawable the exact same variable which is in both XML files.
The missing piece in our puzzle is the activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<data>
<variable
name="drawable"
type="com.example.imagebuttonexperiment.DrawableContainer" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/include_content"
layout="#layout/content_main"
bind:drawable = "#{drawable}"/>
</LinearLayout>
</layout>
RESULT:
The final result is an ImageButton in the MainActivity that was included by another Layout. But the Drawable was chosen from the MainActivity and passed a Container to be shown in the included Layout. Magic isn't it!? ;)
JAVA:
And I will keep my word and provide you the JAVA version also.
The XML files and gradle will be the same, you only need to use MainActivity.java instead of MainActivity.kt, the same for DrawableContainer.java instead of DrawableContainer.kt.
Here is the same in green, DrawableContainer.java:
import android.graphics.drawable.Drawable;
public class DrawableContainer {
public final Drawable customDrawable;
public DrawableContainer(Drawable customDrawable) {
this.customDrawable = customDrawable;
}
}
And of course our MainActivity.java:
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.example.imagebuttonexperiment.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
mainBinding.setDrawable(new DrawableContainer(getDrawable(R.drawable.my_image)));
}
}
DOWNLOAD PROJECT:
In addition I provide the project with both, JAVA and Kotlin classes in it. You just need to comment the content of the 2 classes grey you don't want. In example, if you want to use Kotlin, grey the content of .java files.
Github Project
Documentation & Tutorial:
Databinding Android Documentation
Youtube Tutorial: How to bind data?
NOTE: That's somewhat a solution of my problem:
I have tried this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
colorDialog2=Dialog(this)
colorDialog2.setContentView(R.layout.dialog_colors)
colorDialog2.setTitle("Colors")
firstRowColors=colorDialog2.findViewById<LinearLayout>(R.id.ll_paint_colors)
secondRowColors=colorDialog2.findViewById<LinearLayout>(R.id.ll_paint_colors2)
drawingView=findViewById<DrawingView>(R.id.drawingView)
pressedColor= secondRowColors[0] as ImageButton
pressedColor!!.setImageResource(R.drawable.pallet_pressed)
}
intead of this in Main.Activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
colorDialog=findViewById<LinearLayout>(R.id.dialog_colors)
firstRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors)
secondRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors2)
drawingView=findViewById<DrawingView>(R.id.drawingView)
pressedColor=secondRowColors[0] as ImageButton
pressedColor!!.setImageResource(R.drawable.pallet_pressed)}
And it worked, I managed to change the src however I wanted. (Only did this change didnt do the changes that the others provided) However, I am not even sure if this is a good practice. It works as a quick fix for sure tho.
I will look into DEX7RA's answer more later on.
Hy,
I have a problem, and I can't figure out how to fix it.
So first of all, I used TextInputLayout with AutoCompleteText view, to show a drow down style, and it works well, but when I rotate the screen or couse configuration change like dark mode/light mode switch, the autcompleteTextView doesn't show the dropdown. I know it is an open issue, but I didn't find a working solution.
I tired setFreezesText = false, but it worked when I rotate the screen, and in on configuration change, any other case it didn't work.
layout:
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/opportunity_recording_hr_person_auto_complete_container"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/responsible_hr_person_label">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="#+id/opportunity_recording_hr_person_auto_complete_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
fragment:
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
binding.opportunityRecordingHrPersonAutoCompleteContent.freezesText = false
}
So after that, I changed this, to simple AutoCompleteTextView, and if it gets focus, I show the dropdown list, but unfortunately, it doesn't work, because when configuration changes happen I get this error: Unable to add window -- token null is not valid; is your activity running?
layout:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name_of_project_label"
android:labelFor="#+id/opportunity_recording_customer_auto_complete_content"/>
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/opportunity_recording_customer_auto_complete_content"
android:inputType="text"/>
fragment:
// I call this on onCiewCreated()
private fun initListeners() {
binding.opportunityRecordingCustomerAutoCompleteContent.setOnFocusChangeListener { _, isFocused ->
if (isFocused)
binding.opportunityRecordingCustomerAutoCompleteContent.showDropDown()
}
}
Is there any way to fix one of the problems at least?
I'm struggling with very common problem, I think.
I've created a button in xml file and tagged it with ID. Then I wanted to make onClickListener in MainActivity.kt. But when I'm typing button's ID, it's marked red and it seems like Android Studio doesn't recognise it. I've tried cleaning and rebuilding project, but the problem still exist. Invalidate Caches/Restart didn't help as well.
Here's XML Code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/backgroundColor"
android:fadingEdge="vertical"
android:fadingEdgeLength="80dp"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity"
tools:viewBindingIgnore="true">
<Button
android:id="#+id/btnDateBicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:backgroundTint="#3D446C"
android:text="Select Date"
android:textSize="25sp"
android:textStyle="bold" />
</LinearLayout>
And here's kotlin code
package com.example.ageinminutes
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mybtn = findViewById<btnDateBicker>()
}
}
If you simply want to fetch by id, use findViewById method.
val myBtn: Button = findViewById(R.id.btnDateBicker)
or
val myBtn = findViewById<Button>(R.id.btnDateBicker)
Another way to play with views in the kotlin file:
Try with synthetic binding, like just start writing few words of XML id in your kotlin file and android studio will attach that view for you. [Deprecated after Android 11]
Try with view binding or data binding, you just have to enable these settings in build.gradle file. [More Robust way]
Try this:
val mybtn = findViewById<Button>(R.id.btnDateBicker)
I am very new to Android/Kotlin. I have already created some programs and am making good progress.
But since today I have the problem that I can't get an 'findViewById' running even in the standard 'Hello World' program (Empty Activity).
I have only added the line android:id="#+id/myText" in the XML.
And in MainActivity.kt the line var myTxt = findViewById(android.R.id.myText).
But I get the error message Unresolved reference: 'myText'
The text 'myText' is red.
The usual attempts: Clear Cache, new project, ... I have already tried. The behavior is always the same.
In older projects 'findViewById' is working fine. But I find no difference in Import or settings between working and non working projects.
All in Android Studio 4.1.1
I am grateful for any help
Jan
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/myText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.myhelloworld
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myTxt = findViewById<TextView>(android.R.id.myText)
}
}
android.R.id.something is only used for android's own internal resources. You should remove that and it will work properly.
In kotlin you dont need to set findViewById instead you can just call the TextView name like this: myText.setText(userNameWithMsg)
android. was the problem! I removed it and all is fine again.
Thank you all! Must be a kind of copy paste error ;-))
Now I can go on .....
Great forum!
Thanks a lot
Jan