I am trying to use the documentation example provided in the reference
https://developer.android.com/training/keyboard-input/commands
for implementing the onKeyUp override function. In simplified form this is
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN -> {
// do stuff here
return true
}
else -> super.onKeyUp(keyCode,event)
}
}// end override fun onKeyUp
the problem is that Android Studio doesn't recognize the super.onKeyUp function. Apparently I haven't established the input source correctly as the override isn't recognized either. I can get the result I want, sort of, by starting the class as follows
class KeyboardController(view: View, fragmentActivity: FragmentActivity) : InputController(),
View.OnKeyListener {// start class KeyboardController
then creating the override function
override fun onKey(v: View?, keyCode: Int, event: KeyEvent?): Boolean {
and then checking event.action and testing the key up and down keycodes individually but I seem to be missing something basic in order to use the example code above. Additionally the documentation at https://developer.android.com/guide/topics/ui/ui-events
indicates that View.OnKeyListener class supports the onKeyUp function but as indicated above android studio doesn't recognize the onKeyUp function so I cannot override it. What am I missing or is the documentation wrong?
I am using Android Studio Chipmunk (2021.2.1) with Kotlin.
Any feedback appreciated.
Related
Hello Stackoverflow community,
I am trying to develop an Android application with Mapbox.
I followed this guide to create markers on the map.
https://docs.mapbox.com/android/maps/examples/default-point-annotation/
Thus my code is the following:
public fun createMarker(id: String, lon: Double, lat: Double) {
// Create an instance of the Annotation API and get the PointAnnotationManager.
var marker: PointAnnotation? = bitmapFromDrawableRes(
drawercontext,
R.drawable.red_marker
)?.let {
val annotationApi = binding.mapBoxView.mapView?.annotations
val pointAnnotationManager =
annotationApi?.createPointAnnotationManager(binding.mapBoxView.mapView!!)
// Set options for the resulting symbol layer.
val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
// Define a geographic coordinate.
.withPoint(Point.fromLngLat(lon, lat))
// Specify the bitmap you assigned to the point annotation
// The bitmap will be added to map style automatically.
.withIconImage(it)
// Add the resulting pointAnnotation to the map.
pointAnnotationManager?.create(pointAnnotationOptions)
}
}
Unfortunately, I can not find any solution to add a click listener to markers (to show extra information outside of the map). In my opinion, this should be an important event, so I don't get why there is so little support. I want to replicate something like this:
https://bl.ocks.org/chriswhong/8977c0d4e869e9eaf06b4e9fda80f3ab
But in Android Studio with Kotlin.
One workaround I have seen is to add a click listener to the map and from there determine the marker with the closest coordinates, but I think that would not be as nice of a solution. Do you know any solutions or workarounds to my problem?
Thanks for the help in advance!
try this:
pointAnnotationManager.apply {
addClickListener(
OnPointAnnotationClickListener {
Toast.makeText(this#MainActivity, "id: ${it.id}", Toast.LENGTH_LONG).show()
false
}
)
}
I am new to Android Studio. I wrote a simple code in the main_activity.xml file, with ids. But when I try to reference the ids from my MainActivity.kt file. It shows an error Unresolved reference: btnDatePicker i.e an unresolved error.
I don't know what wrong. Here's a screenshot of my MainActivity.kt file. As you can see, when I try to call the id btnDatePicker, it returns an error.
And Here's a screenshot of my activity_main.xml, as you'll see I have circled the particular id I'm trying to reference.
Id cannot be referenced directly
Under normal conditions, you can bind the control using the following code:
val button = findViewById<Button>(R.id.btnDatePicker)
and if you want to use id directly, i think this article can help you
View Binding
Just try to rebuild project,Build -> Rebuild project
We have 2 variant and I recommend it. I recommend you use View Binding. Because Koltin synthetic(just writing id element) is deprecated.
To enable view binding in a module, set the viewBinding build option to true in the module-level build.gradle file, as shown in the following example:
android {
...
buildFeatures {
viewBinding = true
}
}
Usage
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding(layoutInflater)
val view = binding.root
setContentView(view)
}
then use your xml elements
binding.btnDataPicker.setOnClickListener {
...
}
Just add this in your gradle file in plugins id 'kotlin-android-extensions'
plugins {
id 'kotlin-android-extensions'
}
Just add this in your gradle file in plugins id 'kotlin-android-extensions'
I'm building a weather app using MVVM and retrofit and i recently added a PreferencesFragmentCompat subclass to implement some user settings using the preferences lib. After doing so, my app won't run and i keep getting these few lines of errors :
2020-04-08 00:54:12.346 18079-18079/? E/de.flogaweathe: Unknown bits set in runtime_flags: 0x8000
2020-04-08 00:54:12.410 18079-18079/com.nesoinode.flogaweather E/libc: Access denied finding property "ro.vendor.df.effect.conflict"
2020-04-08 00:54:12.421 18079-18110/com.nesoinode.flogaweather E/Perf: Fail to get file list com.nesoinode.flogaweather
2020-04-08 00:54:12.421 18079-18110/com.nesoinode.flogaweather E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2020-04-08 00:54:12.421 18079-18110/com.nesoinode.flogaweather E/Perf: Fail to get file list oat
2020-04-08 00:54:12.422 18079-18110/com.nesoinode.flogaweather E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
I've got no idea what these are and i can't find any specific answers on stack or google.There are no indications on what is causing the error so i can't figure out if i'm doing something wrong or if it is a library issue. Any ideas?
Here's the SettingsFragment where i'm adding the preferences from an xml resource file :
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.settings_prefs)
}
}
And here's how i'm reading some values from the sharedPrefs:
class UnitProviderImpl(context: Context) : UnitProvider {
private val appContext = context.applicationContext
private val preferences:SharedPreferences
get() = PreferenceManager.getDefaultSharedPreferences(appContext)
override fun getUnitSystem(): String {
val selectedUnitSystemName = preferences.getString(UNIT_SYSTEM_KEY,
UnitSystem.SI.name.toLowerCase(Locale.ROOT))
return selectedUnitSystemName!!
}
}
I managed to figure out a solution to the issue after doing some more research. Firstly, i commented out all the code related to the preferences library (and the lib itself) and run the app again. The run was successful without any errors so that narrowed it down to the androidx.preference:preference-ktx:1.1.0 library itself since my code was reviewed and couldn't find any issues with it. Looking through the preference docs i figured i could try out a beta or alpha version that may have fixed this issue. And lo and behold, after using the androidx.preference:preference-ktx:1.1.0-beta01 beta version and uncommenting the relative code, everything worked once again.
I tried the samples given in github griffon-master, also I tried the samples of the guide.
I would like to use javafx and groovy.
I would like to use fxml - thought of a scenario as that: fxml to set the stage, and for changes, use the groovy (set adjustment)
It seems that is not possible. I can use ("make it run"): javafx-java, read an fxml (with loadFromFXML), and the bindings are working. If using javafx-groovy, I can read an fxml, but with the javafx-class Loader (load), and bindings are not working (or it seems so).
Is it not possible at this moment, to use javafx-groovy and read-in fxml (via loadfromfxml)?
Could you post some sample code? Here's one example that makes use of the fxml node form GroovyFX
package org.example
import griffon.core.artifact.GriffonView
import griffon.metadata.ArtifactProviderFor
import javafx.scene.control.Tab
import org.codehaus.griffon.runtime.javafx.artifact.AbstractJavaFXGriffonView
#ArtifactProviderFor(GriffonView)
class Tab4View extends AbstractJavaFXGriffonView {
FactoryBuilderSupport builder
SampleController controller
SampleModel model
private AppView parentView
void initUI() {
builder.with {
content = builder.fxml(resource('/org/example/tab4.fxml')) {
inputLabel.text = application.messageSource.getMessage('name.label')
bean(input, text: bind(model.inputProperty()))
bean(output, text: bind(model.outputProperty()))
}
}
connectActions(builder.content, controller)
Tab tab = new Tab('Hybrid')
tab.content = builder.content
parentView.tabPane.tabs.add(tab)
}
}
This can be done. The trick is to make your Controller actions adhere to a stringent set of rules. The tldr is to make sure they return void.
Good:
def void save() {
Bad:
def save() {
The reason is found in the reflective analysis the Griffon framework uses to create its list of action targets. This list is generated in DefaultGriffonControllerClass.getActionNames(), which requires that:
Actions are subject to the following rules in order to be considered as such:
must have public (Java) or default (Groovy) visibility modifier.
name does not match an event handler, i.e, it does not begin with on.
must pass {code GriffonClassUtils.isPlainMethod()} if it's a method.
must have void as return type if it's a method.
value must be a closure (including curried method pointers) if it's a property.
The criteria defined in GriffonClassUtils.isPlainMethod() are as follows:
isInstanceMethod(method)
! isBasicMethod(method)
! isGroovyInjectedMethod(method)
! isThreadingMethod(method)
! isArtifactMethod(method)
! isMvcMethod(method)
! isServiceMethod(method)
! isEventPublisherMethod(method)
! isObservableMethod(method)
! isResourceHandlerMethod(method)
! isGetterMethod(method)
! isSetterMethod(method)
! isContributionMethod(method)
The list of action target names is subsequently used by AbstractActionManager:
#Nullable
private static Method findActionAsMethod(#Nonnull GriffonController controller, #Nonnull String actionName) {
for (Method method : controller.getClass().getMethods()) {
if (actionName.equals(method.getName()) &&
isPublic(method.getModifiers()) &&
!isStatic(method.getModifiers()) &&
method.getReturnType() == Void.TYPE) {
return method;
}
}
return null;
}
How can I add an event or other method to listen to keypresses on a gnome shell extension? e.g. show a dialog with each key press showing the pressed key?
I can not find any example. The documentation mentions a keyboard module, but with that common name searching is hard.
Class explanation
...
- General utils
- Keyboard: Manage and define the keyboard events, etc. for gnome shell.
(read above as a quote from the docs linked above. it is styled as code because the quote styling for some reason do not preserve line breaks in this site)
I found some extensions using the bellow code for results similar to what i'm asking, but i, again, failed to find docs for the specific classes and methods:
workViewInjections['_init'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_init', function(width, height, x, y, workspaces) {
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPress));
this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._onKeyRelease));
connectedSignals.push({ obj: global.stage, id: this._keyPressEventId });
connectedSignals.push({ obj: global.stage, id: this._keyReleaseEventId });
});
Also, no class named keyboard anywhere there...
--
edit1: more searching... i think i may have to use the Clutter api. but again, not much examples or documentation for that. farthest i went was this
edit2: more searching. looking on the gnome shell source code, on the main ui tree, i think the answer is to use the barelly mentioned global object that is available to the extension code. e.g.
global.connect('key-press-event', function(if, i, know, the, signature){} );
I came across this snippet in gcampax's gtk-js-app template some time ago, which may be related to what you're doing:
// Due to limitations of gobject-introspection wrt GdkEvent and GdkEventKey,
// this needs to be a signal handler
this.connect('key-press-event', Lang.bind(this, this._handleKeyPress));
and
_handleKeyPress: function(self, event) {
return this.main_search_bar.handle_event(event);
},
I haven't had a need to use keyboard events yet, and this is Gtk in GJS, but the same limitation may be affecting gnome-shell extensions.
UPDATE
I've been doing some keybinding stuff lately, and if attaching a signal handler to the global object is working, you can do something like this:
global.display.connect("key-press-event", (widget, event, user_data) => {
let [success, keyval] = event.get_keyval(); // integer
let keyname = Gdk.keyval_name(keyval); // string keyname
if (keyname === "Control_L") {
// Dialog code or eg. this.keys_array.push("<Ctrl>");
}
});
There's also some Shell keybinding code here and some shell-global documentation here that might give you more clues. Wish I could help more but I'm wrestling my own GJS atm ;)
ADDENDUM
There is a good answer here with an example class with informative logging, as well as a speculative explanation. I've also found this functionality is exposed over DBus which might be more convenient in some cases:
Bus Name: org.gnome.Shell -> Path: /org/gnome/Shell -> Interface: org.gnome.Shell
Relevant Methods:
GrabAccelerator(String accelerator, UInt32 flags) -> (UInt32 action)
UngrabAccelerator(UInt32 action) -> (Boolean success)
Signal:
AcceleratorActivate(UInt32, Dict of {String, Variant})
For me global.stage.connect("key-press-event", _handleKeyPress) did the trick