How to use TextInputLayout & TextInputEditText in Kotlin anko - android

Error:(63, 13) Unresolved reference: textInputLayout
Error:(64, 17) Unresolved reference: textInputEditText
I'm getting above error message when trying to add textInputLayout & textInputEditText in kotlin anko.
Below is my code -
private fun test(context: Context): View{
return with(context){
verticalLayout {
textInputLayout {
textInputEditText{}
}
}
}
}

Create a kotlin code file anywhere you wish. Put below code without any class declaration.
inline fun ViewManager.textInputEditText() = textInputEditText {}
inline fun ViewManager.textInputEditText(theme: Int = 0, init: TextInputEditText.() -> Unit) = ankoView({ TextInputEditText(it) }, theme, init)
inline fun ViewManager.textInputLayout() = textInputLayout {}
inline fun ViewManager.textInputLayout(theme: Int = 0, init: TextInputLayout.() -> Unit) = ankoView({ TextInputLayout(it) }, theme, init)
Hope this helps
EDIT : based on the comment of #A Boschman, anko is very new and there is almost no documentation. When I had the same problem and I search a lot all over internet but didn't find any documentation.
My Solution is based on below mention thread on GitHub - (there also no theoritical explanation)
https://github.com/Kotlin/anko/issues/205
https://github.com/Kotlin/anko/issues/264

TextInputLayout is in the Design Support Library, so you need an additional Anko dependency that gives you bindings for that library (you can find a list of all the different Anko packages here):
compile "org.jetbrains.anko:anko-design:$anko_version"
You'll also need the Design Support Library itself if you don't have it yet:
compile 'com.android.support:design:25.4.0'

Related

Custom lint rule added for a XML Layout tag, doesn't report the issue in layout file

So, I have created a custom lint rule for FlowLayout tag (a 3rd party library) to replace it with ConstraintLayout's Flow feature, here is the code:
class FlowLayoutDetector : LayoutDetector() {
override fun appliesTo(folderType: ResourceFolderType): Boolean {
return ResourceFolderType.LAYOUT == folderType
}
override fun getApplicableElements(): Collection<String>? {
return listOf("com.nex3z.flowlayout.FlowLayout")
}
override fun visitElement(context: XmlContext, element: Element) {
context.report(FLOW_LAYOUT_ISSUE, context.getElementLocation(element), briefMessage)
}
companion object {
private const val briefMessage =
"Please use ConstraintLayout's flow feature, it provides same behaviour as FlowLayout and help us to remove FlowLayout dependency." +
"Visit: https://developer.android.com/reference/androidx/constraintlayout/helper/widget/Flow"
private val IMPLEMENTATION =
Implementation(
FlowLayoutDetector::class.java,
EnumSet.of(Scope.RESOURCE_FILE, Scope.TEST_SOURCES)
)
val FLOW_LAYOUT_ISSUE = Issue.create(
id = "FlowLayoutDetector",
briefDescription = briefMessage,
explanation = briefMessage,
category = Category.CORRECTNESS,
priority = 10,
severity = ERROR,
androidSpecific = true,
implementation = IMPLEMENTATION,
enabledByDefault = true
)
}
}
Added FLOW_LAYOUT_ISSUE into issues list of IssueRegistry.
called ./gradlew lint command, as a result, in the {module-name}-lint-result.xml, it has reported the error:
But in the layout file, no error is reported (unexpected):
Is there any way to get the affect of the custom lint in layout file as well? What am I missing?
I don't know if I arrived too late, but try to delete the content from the baseline file and rerun the command to see if it shows the error on the terminal. When you run the command and there is no baseline file created, it will create the baseline file and will ignore the error.

Calling a Composable function from an android module in the same project

I have an android module (ComposeLib) as part of the same project as the app. It's just to test out using Compose from a library. In the Project Structure dialog I added ComposeLib as an implementation dependency of app.
build.gradle (:app) contains...
dependencies {
...
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.4.0-rc01'
implementation "com.google.accompanist:accompanist-appcompat-theme:0.16.0"
implementation project(path: ':ComposeLib')
...
}
Atoms.kt in ComposeLib consists of...
class Atoms {
#Composable
fun CounterButton(count: Int, updateCount: (Int) -> Unit) {
Button( onClick = {updateCount(count+1)},
modifier = Modifier
.background(MaterialTheme.colors.secondary)){
Text("Clicked $count times")
}
}
}
Then in MainActivity.kt I am trying to use CounterButton...
import com.example.composelib.Atoms
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val myComposeView = findViewById<ComposeView>(R.id.composeView)
myComposeView.setContent {
val counter = remember{ mutableStateOf(0) }
AppCompatTheme {
CounterButton( // <== Unresolved Reference!?
count = counter.value,
updateCount = {newCount -> counter.value = newCount})
}
}
}
}
As you can see in the lower left of the screenshot the app cant find CounterButton from ComposeLib.Atoms. Any idea why?
This code works if I put CounterButton() in the app in MainActivity, so it's not a Jetpack problem it's a build configuration problem.
I also tried qualifying the call to CounterButton every way I could think of (Atoms.CounterButton, public.example.composelib.Atoms.CounterButton, etc). Even code completion doesn't recognize it.
How do I reference a #Composable function from another module in the same project?
You've defined your Composable inside class Atoms for some reason, so this function should be called on a class instance.
It's totally fine to define composable functions without any classes, just like
#Composable
fun CounterButton(count: Int, updateCount: (Int) -> Unit) {
}
It's already in some package so I don't think any container is much needed. But in case you wanna add some kind of modularity, you can replace class with object, in this case you'll be able to call it as Atoms.CounterButton

Kotlin issue when trying to cast "attachBadgeDrawable": This declaration is opt-in

I would use the BadgeDrawable in my Android app on a Button, the issue is that when i'm trying to set to the button layout the badgeDrawable via attachBadgeDrawable i get an error on it which says:
his declaration is opt-in and its usage should be marked with '#com.google.android.material.badge.ExperimentalBadgeUtils' or '#OptIn(markerClass = com.google.android.material.badge.ExperimentalBadgeUtils.class)'
The code where i use that piece of code is the following:
btnInvia.viewTreeObserver.addOnGlobalLayoutListener(
object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
val badgeDrawable = BadgeDrawable.create(requireContext())
badgeDrawable.number = corpo
badgeDrawable.verticalOffset = 20
badgeDrawable.horizontalOffset = 15
BadgeUtils.attachBadgeDrawable(badgeDrawable, btnInvia, layoutInvia)
btnInvia.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
)
if it could be usefull the min SDK is 24.
The class BadgeUtils is marked with the androidx annotation #Experimental. In this way it is reported the usages of experimental API in this case with a level = ERROR.
In your method you have to use one of these annotations to suppress the report:
#ExperimentalBadgeUtils
#UseExperimental(markerClass = ExperimentalBadgeUtils::class)
fun onCreate(savedInstanceState: Bundle?) {
//...
btnInvia.viewTreeObserver.addOnGlobalLayoutListener(
//..
)
}
You can also use the kotlin annotation #OptIn:
#OptIn(ExperimentalBadgeUtils::class)
fun onCreate(savedInstanceState: Bundle?) {
//...
btnInvia.viewTreeObserver.addOnGlobalLayoutListener(
//..
)
}

Why extension function is not visible in another module?

My Android project has two modules:
app
common
In settings.gradle:
rootProject.name='My project'
include ':app'
include ':common'
In my build.gradle:
implementation project(':common')
In common package I has StringUtil.kt with the next extension function:
fun String.isEmailValid(): Boolean {
return !TextUtils.isEmpty(this) && android.util.Patterns.EMAIL_ADDRESS.matcher(this).matches()
}
And in this class I can use extension function like this:
val str = ""
str.isEmailValid()
But in app module I has class
class RegistrationViewModel(application: Application) : AndroidViewModel(application) {
fun doClickRegistration(email: String?, password: String?, retypePassword: String?) {
val str = ""
str.isEmailValid()
}
}
But now I get compile error:
Unresolved reference: isEmailValid
If you do not specify any visibility modifier, public is used by default, which means that your declarations will be visible everywhere; (Source)
Since you didn't add any visibility modifier to isEmailValid it is regarded as public.
Please note that extension functions have to be imported.
import com.your.package.path.isEmailValid
In your app build.gradle add this:
implementation project(':common')

Is an implicit property type same with an explicit property type?

The following Code A is from Kotlin-for-Android-Developers. The Code B is written by me.
Do these two different blocks of code function the same way?
Code A
class DetailActivity : AppCompatActivity(), ToolbarManager {
override val toolbar by lazy { find<Toolbar>(R.id.toolbar) }
...
}
Code B
class DetailActivity : AppCompatActivity(), ToolbarManager {
override val toolbar: Toolbar by lazy { find<Toolbar>(R.id.toolbar) }
...
}
From the structure point of view, they are the same. the Kotlin compiler will emits the same java byte code of the source code both likes as below:
private final Lazy<Toolbar> toolbarProvider = lazy(()-> find(R.id.toolbar));
public Toolbar getToolbar(){
return toolbarProvider.getValue();
}
the property type is optional in code B above, but it is useful when programming by interface rather than implementation [1], if the implementation was changed the only one need to change is where it is instantiated, since the usage of the toolbar can't access the features declared by its sub-classes at all. for example:
//declare as abstract supertype ---v
override val toolbar: AbstractToolbar by lazy { find<Toolbar>(R.id.toolbar) }
// ^
//when implementation was changed only need to change here.
//e.g:change the `Toolbar` to other subtype of AbstractToolbar: find<MiniToolbar>()
From the compiler point of view, they are different. Since the compiler will infer the actual property type in the code A at compile-time, for example:
// v--- the property type `Toolbar` is inferred at compile-time
override val toolbar/*:Toolbar*/ by lazy { find<Toolbar>(R.id.toolbar) }
[1]: https://en.wikipedia.org/wiki/Liskov_substitution_principle

Categories

Resources