After migrating my project to AndroidX using the Migrate to AndroidX... functionality provided by Android Studio and having made changes to my dependencies accordingly to have everything running like it is supposed to, I have encountered a minor problem which I haven't been able to resolve.
To set a device number in my application I used an EditTextPreference like the following defined in my pref_screen.xml which is set in a PreferenceFragmentCompat class with
setPreferencesFromResource(R.xml.pref_screen, string):
<EditTextPreference
android:icon="#drawable/ic_perm_device_information_black_24dp"
android:inputType="number"
android:key="change_device_id"
android:maxLines="1"
android:selectAllOnFocus="true"
android:singleLine="true"
android:summary="#string/settings_device_id"
android:title="#string/pref_title_change_device_id" />
It used to show a numeric keyboard to change the value but after migrating to AndroidX it keeps showing a normal keyboard as shown in the image below. I tried changing the inputType and defining the decimals in xml but to no avail. Has something changed to set the inputType for the keyboard after migrating to AndroidX or am I missing something obvious?
android:inputType="numberDecimal"
android:digits="0123456789"
From an answer here:
https://stackoverflow.com/a/55461028/7059947
Cast your Preference to EditTextPreference and use setInputType On Bind.
This saved my day :)
EditTextPreference edpPrefernce = (EditTextPreference) pPreference;
edpPrefernce.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
#Override
public void onBindEditText(#NonNull EditText editText) {
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
}
});
Google has not fixed this yet. You can use takisoft's fix for this problem:
https://bintray.com/takisoft/android/com.takisoft.preferencex%3Apreferencex/1.0.0
Add to build.gradle (project):
buildscript {
...
repositories {
maven {
url "https://dl.bintray.com/takisoft/android"
}
}
....
}
Add to build.gradle (app module):
implementation 'com.takisoft.preferencex:preferencex:1.0.0'
Change the imports in your classes and the components in your XML resources:
androidx.preference.EditTextPreference -> com.takisoft.preferencex.EditTextPreference
androidx.preference.PreferenceCategory -> com.takisoft.preferencex.PreferenceCategory
androidx.preference.PreferenceFragmentCompat -> com.takisoft.preferencex.PreferenceFragmentCompat
In your PreferenceFragmentCompat subclass, change the onCreatePreferences(...) declaration to onCreatePreferencesFix(...).
... and voila! The old parameters, like numeric and singleLine will be back and work!
[Solved]
Add to build.gradle (app module):
implementation 'androidx.preference:preference:1.1.0-rc01'
Related
I know this is probably a quite simple question to answer but I want to import my button from activity_main.xml with the id "button1":
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
In the MainActivity.kt so I can add a setOnClickListener to it.
I saw something like this:
MainActivity.kt:
val button1 = findViewById(R.id.button1) as Button
That gives me 2 errors:
unresolved reference: findViewById;
unresolved reference: Button;
This is the action I want to add:
button1.setOnClickListener {
Toast.makeText(applicationContext, "Hello World", Toast.LENGTH_LONG).show()
}
So I could use the setOnClickListener on "button1" but it wont work.
Whats the standard way of importing a button with kotlin so I can use it properly?
So apparently, I needed to add
apply plugin: 'kotlin-android-extensions'
to the build.gradle (Module:app).
After that I was able to import all views via
import kotlinx.android.synthetic.main.activity_main.*
on the MainActivity.kt so I could use the setOnClickListener to the Id I gave the button in the activity_main.xml
I think the findViewById() is just another way to do this, still good. Thanks
You Could Do This:
val button1 = findViewById<Button>(R.id.button1)
In your code, make sure that the Button and findViewById both were referenced from Activity class.
There are different ways for view binding. The recommended one is to use either data binding or view binding feature.
Kotlin synthetics, part of Android Kotlin Extensions Gradle plugin, is Kotlin only method of view binding which doesn't expose nullabilty. That means all the views are declared as platform types. Now beginning from Kotlin 1.4.20, they will not be supported. Check migration to view binding here: https://developer.android.com/topic/libraries/view-binding/migration
findVewbyId is another way for the same purpose, but this comes with some expenses like traversing the view hierarchy to get the view, runtime exceptions, boilerplate code.
Other way is to use library like ButterKnife
I have just started Android Development with a basic app which takes the username and display in Toast but came across an error in the main activity. It says "Unresolved references: editName". I tried making the app again, manually importing editText widget and changing the id name but nothing works.
It would be great if someone can tell me what's going wrong.
ScreenShot of the code with error underlined with red..... Module build.... Project build
I'll show you the example in Java.
You must create a variable in your activity class
EditText editName;
then you must override the onCreate() method of the Activity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
editName = (EditText) findViewById(R.id.editName);
}
overriding the onCreate() you can take a reference to your EditText.
If you're following a tutorial, they're probably expecting you to use Kotlin Synthetic Binding which means you need this in your build.gradle:
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
That will automagically create variables for each View in the layout that has an ID assigned - so if you have an EditText with an ID of editName, then a val editName: EditText will be created in the background when you inflate the layout. Yes it's magic, yes it trips everyone up and accounts for a lot of the problems people run into on here!
Savatore's answer is the normal, standard, non-magical way of doing it. If you want the convenience, look into the View Binding library, which is the official way of automatically binding views to variables (Kotlin synthetics are deprecated)
I am trying to link a function to the onClick property of a button in AndroidStudio but for some reason the system cannot identify the method that I coded.
The funny thing is that it works correctly when I code it in Java. In Kotlin it does not. I updated my Kotlin and checked its configuration but I cannot find the problem. My friend tried the same thing I did in a Linux computer and it worked for him. I have a Mac OS, I don't know if there is some extra configuration to take care of. Can anyone help me?
This is my simple activity:
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun sendMessage(view: View) {
}
}
This is the xml:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:onClick="sendMessage"
android:text="#string/send_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/editText"
app:layout_constraintTop_toTopOf="parent" />
In build.gradle I have:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
Error message:
Corresponding method handler 'public void sendMessage(android.view.View)' not found
The onClick attribute value should be the name of a method in this View's context to invoke when the view is clicked.
This name must correspond to a public method that takes exactly one parameter of type View. Must be a string value, using '\;' to escape characters such as '\n' or '\uxxxx' for a unicode character
Try to add
tools:context="com.somepackage.MainActivity"
to your top view in xml
It works now. I had to restart AndroidStudio. I still cannot add the function using the attributes window in the design tab but it works if I edit the XML directly.
I'm writing my first Android app and it involves a preference where you set an amount of minutes, from 0 to 60. I've used a SeekBarPreference, and it shows up as a simple slider which you can indeed slide around to edit the value. The preference works fine.
I would like to show the selected value next to the SeekBar (or somewhere in the vicinity), as there by default is no way for the user to see what they've actually selected. There are lots of questions on Stack Overflow about similar sliders and preferences, but since version 25.1.0, released last December, there is SeekBarPreference, which has just what I need:
The seekbar value view can be shown or disabled by setting showSeekBarValue attribute to true or false, respectively.
But among the public methods listed below, there is no method for setting showSeekBarValue? There is a method for setting the adjustable attribute, setAdjustable(boolean adjustable), however?
Ideally I'd just write android:showSeekBarValue="true" in my SeekBarPreference tag in preferences.xml, but that (obviously) doesn't work.
So in a nutshell: how do I set showSeekBarValue to true?
In the app's build.gradle, I had to add
implementation 'com.android.support:preference-v7:26.+
Then, modify the PreferenceScreen's xml to include an app namespace:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
Finally, inside the xml, you can add
<SeekBarPreference
android:key="..."
android:title="..."
android:max="100"
android:min="0"
android:defaultValue="30"
android:dependency="..."
app:showSeekBarValue="true"
/>
This compiles without errors. To be fair, this is not a complete answer, because no value is shown in my case, even after these steps. But formally it does let you set the value in some way.
You need to use PreferenceScreen from android.support.v7.preference
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<SeekBarPreference
android:key="size"
android:title="Size"
android:summary="size of progressBar in dp's"
android:max="100"
app:showSeekBarValue="true"
android:defaultValue="25" />
</android.support.v7.preference.PreferenceScreen>
and also PreferenceFragmentCompat from android.support.v7.preference
import android.support.v7.preference.PreferenceFragmentCompat
class SettingsFragment: PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
}
}
I'm trying to use android databinding. But I got some problem when I use android:visibility with condition. Like android:visibility="size == 0 ? View.GONE : View.VISIBLE".
When it returns false, it will show this view first, then for a while it turns to gone.
Can I fix this? Or is this the databing's bug?
I ever tried code like this
android:visibility="#{size==0?View.GONE:View.VISIBLE}",
but it can not be compiled.I don't know why, maybe it is a bug.
So I using code following instead, firstly, write a Helper.
public class Helper {
#BindAdapter("bind:attr")
public static void setAttr(View view, Object obj) {
if (someCondition(obj)){
view.doSomething();
}
}
}
secondly, using custom attr in xml file
<View
...other attrs...
app:attr="#{obj}" />
note:
the 'attr' in the annotation must be the same with 'attr' used in xml file.
the View in the static method must be the same with the View in xml file.
My Gradle version and dataBinder version
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath "com.android.databinding:dataBinder:1.+"
}
And, remove other operations unrelated on this view.
Or offer your activity code.