Open pianocomposer321 opened 5 months ago
Good questions, I'm moving this into the docs repo. I'll try to answer the questions here, since a proper docs page will require more than a few bullet points...
@nativescript/core
provides it. It's technically a no-op decorator that gets stripped out during bundling, it's used to signal to webpack/typescript (with a custom transformer) that this class should be converted to es5 syntax in the bundle, as the runtime understands es6 syntax fine, but when extending native classes, the mechanisms used only work on es5 classes (the v8 javascript engine doesn't expose the necessary hooks when using es6).android.widget.Button
doesn't need to be imported either, because those are directly mapped to their native counterparts/java namespaces. For example the following java code (from a 3rd party/plugin/App_Resources - doesn't matter)
package foo.bar.baz;
public class MyClass {}
Would allow you to access it from your javascript through it's fully classified name (meaning, namespace + class name):
const myClassInstance = new foo.bar.baz.MyClass();
no imports needed - it's a "java" global.
For widgets and whatnot, you would subclass View
and implement the createNativeView
method, for a very simple example, let's do a Button widget with a custom subclassed android.widget.Button
:
// example.ts
import { View } from "@nativescript/core";
@NativeClass
class MyButton extends android.widget.Button {
constructor() {
super()
// necessary when extending TypeScript constructors
return global.__native(this)
}
setEnabled(enabled: boolean): void {
this.super.setEnabled(enabled)
}
}
export class MyNativeScriptButtonView extends View {
createNativeView() {
return new MyButton();
}
}
There's a few ideas in this example worth mentioning:
MyButton
will be a proper java class, but it's namespace will be "random", this means any java method that expects a android.widget.Button
(or a View instance) will happily accept this as a parameter.@JavaProxy('foo.bar.baz.MyButton');
decorator along with the @NativeClass
decorator to make sure the namespace is not "random". This way you can pass it into stuff like AndroidManifest.xml and whatnot (not a great example in case of a widget, but let's say you subclass the Activity, then you'd want to declare it in the manifest, this is where the JavaProxy
decorator helps).MyNativeScriptButtonView
is a NativeScript wrapper around the MyButton
native widget, this makes it work with the nativescript view hierarchy, css etc.MyNativeScriptButtonView
:
Vue.registerElement('MyNativeScriptButtonView', () => MyNativeScriptButtonView);
. Then you use it like any other view in your template: <MyNativeScriptButtonView />
registerElement
function that tells the renderer what that view/element is.<GridLayout xmlns:mynamespace="./example">
<mynamespace:MyNativeScriptButtonView />
</GridLayout>
There's a lot to unpack, but once you understand the basics, it's fairly straight forward to follow. I always recommend reading code in @nativescript/core
itself, as all the built-in views are implemented this way. The above is definitely a reduced example, as it doesn't really touch on the property system in core, css properties etc.
For reference, see the Android implementation of the default <Button>
element: https://github.com/NativeScript/NativeScript/blob/main/packages/core/ui/button/index.android.ts
Is your feature request related to a problem? Please describe.
I need to have access to a native method for the ListView component. The documentation is very unclear about how I would go about doing this. It says that I can subclass android components and has a short example of what this would look like, but the example is frankly very unhelpful:
This example refers to the
NativeClass
decorator and theandroid.widget.Button
class. Presumeable these would have to be imported from some nativescript modules, but there are no import statements at the top of the file. Where are these coming from? Also, how do I then use this class after extending the base class? If I want it to show up in a stack layout on my main page, for example, how would I do this using nativescript? What about with Vue? Or Svelte? Just instantiating it at the bottom of the file does nothing to tell the application where it should be placed. Also, do I need to place this code in some specific file or directory for it to be picked up by the rest of my code, like from the .xml file?None of this is mentioned.
Describe the solution you'd like
I'd be satisfied if someone could answer my questions here, but I think the documentation could benefit a lot from this information being added to it directly.
Describe alternatives you've considered
I've searched through the docs, and searched the web too. Nothing is helpful.
Anything else?
No response
Please accept these terms