I have a webpage that repeats a button action when held down. It works great, except the phone then vibrates. Is there a way to disable vibrating?
This solution wouldn't work for anyone that needs some form of haptic feedback. However, I do not, and here is the magic line that fixed it:
webView.setHapticFeedbackEnabled(false);
To disable vibrating on longpress use,
#Override
public void onLongPress(MotionEvent e) {
AudioManager audio=(AudioManager)getSystemService(AUDIO_SERVICE);
audio.setRingerMode(audio.RINGER_MODE_SILENT);
}
Then set it back if required.
Related
I have got an old C++ MFC app upgraded to use the WebView2 web browser control, based on Edge. Otherwise I have got it working fine, one of the remaining issues is opening the Find dialog in it via the main MFC app Edit-Find menu item or via Ctrl+F (which is also intercepted by MFC framework). What I have now is:
m_webView->ExecuteScript(L"window.find(\"\", 0, 0, 0, 0, 0, 1);");
where m_webView is a pointer to ICoreWebView2 interface.
The problem is that sometimes it does bring up the Find dialog, sometimes not. Sometimes it does it after page refresh, sometimes not. When I close the Find dialog from cross, it typically refuses to open it again.
How can I make it behave properly? Maybe there is a way which does not need to go through Javascript?
Update: it appears it only worked if the Ctrl+F keystroke was somehow sent directly to the WebView2 control, bypassing MFC. It looks like the above Javascript line never worked. So maybe there is a way to simulate Ctrl+F for the WebView2 control?
AFAIK, WebView2 currently has no support for you invoking or otherwise controlling the find in page dialog. You can also refer to this thread. There is a similar thread in GitHub and the official hasn't given a solution.
You can use Ctrl+F keystroke directly in WebView2 control or provide feedback about this issue on WebView2 Feedback page. Thanks for your understanding.
As #yu-zhou answered, there is no official way yet to do what I wanted. For now I resorted back for emulating Ctrl+F programmatically for the WebView2 control, but the result ain't so pretty. For the record I still present it here:
First, the user has to click in the webview2 control at least once, so I can record its HWND in the GotFocus event handler registered by add_GotFocus():
void MyHtmlView::OnGotFocus() {
if (!m_webview2_hwnd) {
m_webview2_hwnd = ::GetFocus();
}
}
Now, when I want to bring up the Find bar programmatically, I need to ensure the correct window is focused and send it the Ctrl+F key. Alas, it appears the control checks the Ctrl key state in async way, so it gets a bit tricky, I need to alter the keyboard state for the thread and add an extra event handler for restoring it afterwards. After some trial and error I reached this (error checks omitted for brevity):
void MyHtmlView::Find() {
if (::GetFocus()!=m_webview2_hwnd) {
::SetFocus(m_webview2_hwnd);
}
std::uint8_t state[256];
::GetKeyboardState(state);
bool restoreCtrlState = false;
if ((state[VK_CONTROL] & 0x80)==0) {
// Ctrl key is currently not pressed.
// Mark it pressed.
state[VK_CONTROL] |= 0x80;
::SetKeyboardState(state);
restoreCtrlState = true;
}
std::thread auxThread([this, restoreCtrlState]() {
::SendMessage(m_webview2_hwnd, WM_KEYDOWN, 'F', 1);
::SendMessage(m_webview2_hwnd, WM_KEYUP, 'F', 1);
if (restoreCtrlState) {
::PostMessage(m_hWnd, WM_COMMAND, ID_RESTORE_CONTROL_STATE, 0);
}
});
auxThread.detach();
}
// This needs to be registered to handle ID_RESTORE_CONTROL_STATE
void HtmlView::OnRestoreCtrlState() {
std::uint8_t state[256];
::GetKeyboardState(state);
if ((state[VK_CONTROL] & 0x80)!=0) {
state[VK_CONTROL] &= ~0x80;
::SetKeyboardState(state);
}
}
Needless to say, this hack may easily cease to work if they change something in the webview2 implementation.
What I am wanting to do is simple. I am using UrbanAirship to show a modal view ("In-app Automation"), which is HTML. I have a button in my HTML. The message/view is showing fine when the event is fired. Right now I have in the HTML for the button:
<button class="light" type="button" onclick="UAirship.close()">OK</button>
When the button is tapped, the call to UAirship.close() works fine and closes the message. I setup a listener in my Android code, such as follows:
UAirship.shared()
.getInAppMessagingManager()
.addListener(new InAppMessageListener() {
#Override
public void onMessageDisplayed(#NonNull String scheduleId, #NonNull InAppMessage message) {
// gets here fine
}
#Override
public void onMessageFinished(#NonNull String scheduleId, #NonNull InAppMessage message, #NonNull ResolutionInfo resolutionInfo) {
// gets here fine as well
}
});
It gets into those methods without any issues when the message/view shows and dismisses. However, I want to be able to detect one particular button was tapped vs. others I have in the HTML. Is there a way to go about this easily, so that some custom tag or something can be passed in the "ResolutionInfo" object or "InAppMessage"?
My hopes were that there would be something like "UAirship.close('tag')", where that tag would be passed back. Or even a custom HTML tag I can put on the button that would be recognized in the code. Really just any way of going about it is fine, I just can't seem to find in the documentation how to properly do this with HTML.
I'm looking at the documentation here. I see the UAirship.runAction() method, but it's not really clear to me what a simple implementation would be for this (also, the "CustomAction" class referenced in the action registering doesn't even exist in the library it seems..).
I basically just need to call one line of code in my Activity when the Airship message closes after that button is tapped.
Thoughts?
I've found that this solution works, although there may be a better one out there.
In the HTML, for the button, call the close() and then a runAction() call:
onclick="UAirship.close(); UAirship.runAction('my_action', null, null)"
Then in the code, in my onCreate() in my Activity, I have this:
final String actionName = "my_action";
Action customAction = new Action() {
#NonNull
#Override
public ActionResult perform(#NonNull ActionArguments actionArguments) {
String buttonActionName = actionArguments.getMetadata().getString(ActionArguments.REGISTRY_ACTION_NAME_METADATA);
if (buttonActionName.equals(actionName)) {
// DO WHAT IS NEEDED HERE
}
return ActionResult.newEmptyResult();
}
};
UAirship.shared()
.getActionRegistry()
.registerAction(customAction, actionName);
I have a chromiumBrowser(cefsharp) in my solution and I want to perform a regular Google Map search using the search bar in Google Maps.
I have basically no Javascript/Lambda experience, but I have done my best with googling and have only come up with reading what is in the searching box, filling it out, then click()ing the search button next to it.
The issue is, it only sometimes takes the first click(). Google Maps seems to need at least a real keyboard input change event on the search Bar.
I need a search rather than a load(URL) because search smoothly scrolls to the new destination, vs load(URL) which will white screen and then warp to the destination.
I've tried using simulated coordination mouse clicks (I can open the menu panel, yay?) but not trigger the searchbox triggers. I've tried click() on the searchbox, but I can't get keydown or keypress to work with my limited JS/HTML knowledge.
private void button1_Click(object sender, EventArgs e)
{
cBrowser.ExecuteScriptAsync("document.getElementById('searchboxinput').value='" + textBox1.Text + "'");
}
private void button2_Click(object sender, EventArgs e)
{
cBrowser.ExecuteScriptAsync("document.getElementById('searchboxinput').focus({})");
cBrowser.ExecuteScriptAsync("document.getElementById('searchboxinput').places_changed()");
cBrowser.ExecuteScriptAsync("document.getElementById('searchboxinput').focus({})");
}
private void button3_Click(object sender, EventArgs e)
{
cBrowser.ExecuteScriptAsync("document.getElementById('searchbox-searchbutton').click()");
}
private void button4_Click(object sender, EventArgs e)
{
int x = 25; int y = 60;
cBrowser.GetBrowser().GetHost().SendMouseClickEvent(x, y, MouseButtonType.Left, false, 1, CefEventFlags.None);
Thread.Sleep(15);
cBrowser.GetBrowser().GetHost().SendMouseClickEvent(x, y, MouseButtonType.Left, true, 1, CefEventFlags.None);
}
So it takes the first click(). But the second and thereon, the button click() does nothing. It acts as though the new input in searchbox never happened and the searchBox reverts.
The button click() only takes if I really click on the searchBox and let the triggers fly. Can someone please help me figure out the code to trigger the underlying requirements of the searchbox so I can click() the searchbox to search to the next area?
Update
Using How do I view events fired on an element in Chrome DevTools? I think I have the events, but now how do I send that same event to Google Maps and have it cascade and run all the other functions a regular click/type triggers?
textInput > TextEvent {isTrusted: true, data: "a", view: Window, detail: 0, sourceCapabilities: null, …}
input > InputEvent {isTrusted: true, oM: "input", data: "a", isComposing: false, inputType: "insertText", …}
I'm assuming I have to send a textInput/input event with a textEvent/inputEvent Object. I cannot create neither in C#, so I guess I have to lump it all into a single js script, the element, event, and event object somehow?
I think I have to do something like this. But the default InputEvent is super large, and I can't find the constructor neither.
cBrowser.ExecuteScriptAsync("document.getElementById('searchboxinput').dispatchEvent(new InputEvent(isTrusted=true, data=\"f\", isComposing=false, inputType=\"insertText\", dataTransfer=null))");
"Uncaught TypeError: Failed to construct 'InputEvent': parameter 2 ('eventInitDict') is not an object.", source: about:blank (1)
And am I wrong to think that data="f" is not correct and I have to feed it a eventInitDict? Where would I even get or find that!
Does anyone have an idea or an example code that can trigger this? Even just a JS code might help (might be able to just plug that into ExecuteScriptAsync?).
How to simulate key press event?
I eventually just settled on the answer for this question. Which is sendkeys to the cefsharp browser. Works fine, just gotta set it as control/active first. Not perfect but got the job done.
I am totally new in phonegap/cordova development and I have a problem with the keyboard on cordova webview for my app.
What I am trying to achieve is to have an input text with keyboard type that only shows numeric pad (which is type="tel") and also hides the characters that are typed into the input textbox (which is type="password"). What I have tried to achieve this behaviour is by changing the input type twice with javascript. Here's the code for that :
<script>
function changeInputType(){
document.getElementById("txtPin").setAttribute("type", "tel");
setTimeout(function(){document.getElementById("txtPin").setAttribute("type", "password");}, 750);
}
</script>
//here is how I use it on the html input
<input type = "tel" id="txtPin" onlick="changeInputType()" onkeypress="changeInputType()"/>
This dirty trick works fine when the user types on the textbox, but when the keyboard is present and I press the home button or do whatever that results to the app being sent to the background, and then I go back to open the app again, the keyboard type will change to the default text keyboard. And the javascript seems to not work anymore when I dismiss the keyboard and then open it up again by clicking on the textbox.
So, if anyone has any idea what I'm doing wrong here or has any suggestion on what I can do to fix this problem, please help.
Thank you! cheers!
I found out that to make the keyboard go back to numeric (type="tel") again is to call the javascript method on my AppDelegate through the current visible view controller like so :
//get the current visible view controller
UIViewController *viewController = ((UINavigationController*)self.window.rootViewController).visibleViewController;
if([viewController isKindOfClass:[MyViewController class]])
{
MyViewController *vc = (MyViewController *)viewController;
if(vc.webView respondsToSelector:#selector(stringByEvaluatingJavaScriptFromString:)
{
//call the javascript function on the webview
[vc.webView stringByEvaluatingJavaScriptFromString:#"changeInputType"];
}
}
I'm having a heckuva time trying to find a way to use javascript or css (not Java) to prevent Android devices from showing the pop up dialog when long-pressing on an html element like an image or anchor in a web page.
I'm trying to make a carousel and if I hold the left or right arrow down on my carousel, a window pops up asking me to open in a new tab, save the image, etc. I can do this easily enough on iOS/Safari with a css rule.
Thanks in advance.
how are you setting your setOnLongClickListener and onTouch?
make sure it's similar to this
setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View view) {
activity.openContextMenu(view);
return true; // avoid extra click events
}
});
setOnTouch(new View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent e){
switch(e.getAction & MotionEvent.ACTION_MASK){
// do drag/gesture processing.
}
// you MUST return false for ACTION_DOWN and ACTION_UP, for long click to work
// you can return true for ACTION_MOVEs that you consume.
// DOWN/UP are needed by the long click timer.
// if you want, you can consume the UP if you have made a drag - so that after
// a long drag, no long-click is generated.
return false;
}
});
setLongClickable(true);
code curtosy of Sanjay Manohar
Detect touch press vs long press vs movement?