Context: I am developing a mobile Shiny app using the shinyMobile package, which is a wrapper for the famous framework7 HTML template.
In my app, the user has to make a selection of attributes on a first tab using multiple dropdown lists, and then, on the other tabs, some output is produced. Each tab requires the user to scroll up and down to access all the content and in this process, very often the 'pull to refresh' feature is triggered.
This is really annoying, because the entire attribute selection and output are lost, and the user has to start over from scratch.
What I tried: based on this SO thread which pointed me to this Google developer page, I tried setting the CSS overscroll-behavior property to contain with: body {overscroll-behavior-y: contain;}. PROBLEM: It does not work for me! (tested on Chrome Android)
Minimal reproducible example:
default app, deployed here
library(shiny);library(shinyMobile)
shiny::shinyApp(
ui = f7Page(
f7Card(
h5('try to pull to refresh. normally it should work.')
)
),
server = function(input, output) {}
)
Supposedly fixed app, deployed here
library(shiny);library(shinyMobile)
shiny::shinyApp(
ui = f7Page(
tags$style(type='text/css', '.body{overscroll-behavior-y: contain;}'),
f7Card(
h5('try to pull to refresh. Normally it should not work.')
)
),
server = function(input, output) {}
)
Hope you guys can reproduce my issue and identify what is amiss!!!
You might want to change your css part to: html,body{overscroll-behavior-y: contain;}, see https://stackoverflow.com/a/42509310/3502164.
Then it works for me on my mobile (android chrome).
Reproducible example:
library(shiny)
library(shinyMobile)
app <- shiny::shinyApp(
ui = f7Page(
tags$style(type='text/css', 'html,body{overscroll-behavior-y: contain;}'),
f7Card(
h5('try to pull to refresh. Normally it should not work.')
)
),
server = function(input, output) {}
)
# use host config to access app from mobiles in the same network
shiny::runApp(appDir = app, host = '0.0.0.0')
Related
thanks for checking my question out!
I'm currently working on a project using Qt C++, which is designed to be multi-platform. I'm a bit of a newcoming to it, so I've been asked to set up the ability to take screenshots from within the menu structure, and I'm having issues with the Android version of the companion app.
As a quick overview, it's a bit of software that send the content of a host PC's screen to our app, and I've been able to take screenshots on the Windows version just fine, using QScreen and QPixmap, like so:
overlaywindow.cpp
{
QPixmap screenSnapData = screenGrab->currentBackground();
}
screenGrabber.cpp
{
QScreen *screen = QGuiApplication::primaryScreen();
return screen->grabWindow( QApplication::desktop()->winId() );
}
Unfortunately, Android seems to reject QScreen, and with most suggestions from past Google searches suggesting the now-deprecated QPixmap::grab(), I've gotten a little stuck.
What luck I have had is within the code for the menu itself, and QWidget, but that isn't without issue, of course!
QFile doubleCheckFile("/storage/emulated/0/Pictures/Testing/checking.png");
doubleCheckFile.open(QIODevice::ReadWrite);
QPixmap checkingPixmap = QWidget::grab();
checkingPixmap.save(&doubleCheckFile);
doubleCheckFile.close();
This code does take a screenshot, but only of the button strip currently implemented, and not for the whole screen. I've also taken a 'screenshot' of just a white box with the screen's dimensions by using:
QDesktopWidget dw;
QWidget *screen=dw.screen();
QPixmap checkingPixmap = screen->grab();
Would anyone know of whether there was an alternative to using QScreen to take a screenshot in Android, or whether there's a specific way to get it working as compared to Windows? Or would QWidget be the right track? Any help's greatly appreciated!
as i can read in Qt doc : In your screenGrabber.cpp :
QScreen *screen = QGuiApplication::primaryScreen();
return screen->grabWindow( QApplication::desktop()->winId() );
replace with :
QScreen *screen = QGuiApplication::primaryScreen();
return screen->grabWindow( 0 ); // as 0 is the id of main screen
If you want to take a screenshot of your own widget, you can use the method QWidget::render (Qt Doc):
QPixmap pixmap(widget->size());
widget->render(&pixmap);
If you want to take a screenshot of another app/widget than your app, you should use the Android API...
Testing a Progressive Web Application.
When I start the app in airplane mode, I get an unexpected startup/splash experience (Android/Chrome).
Launch from Home Screen Experience
I see a white screen, followed by a brief flash of the "offline dinosaur" before the app successfully starts and all is well. The startup time is longer than I expected, especially after testing with Chrome Devtools on a laptop, where startup is near instant.
Since it is a little tricky to debug where this time is being spent (especially in the “service-worker-not-running” case), it would be helpful to have some baseline knowledge:
Launch from Browser Experience
Just a brief flash of the "offline dinosaur" before the app successfully starts. Starts much faster.
Questions
What is the expected startup time and experience on Android/Chrome?
Is the experience described above just the current state of things (11/2015)?
Is there any way to specify the startup (splash) experience for Chrome? (I'm aware of background color and 144x144 icon in app manifest for splash, but for Opera only)
First time PWA for me, so any information on this would be helpful.
My platform:
Samsung GS 5,
Android 5.0,
Chrome 46.0.2490.76
The reason for the existence of the splash screen is because on mobile it can take over a second to start the render process so we paint something (the background colour and icons) util you have a first paint generated by your app.
If you are seeing a white screen on startup it might be because you added to the homescreen prior to Chrome landing (46) the splash screen feature. Some things to lookout for:
Ensure your manifest has a short_name and name
Ensure your start_url is in the same scope as a SW that is registered on the page
Have good icons in the manifest ideally > 192px
Set background_color in the manifest to the color of your background on the page (ideally.) This will ensure that the splash screen is the expected colour of your site.
You shouldn't see the offline dinosaur at all, even when you are in aeroplane mode. Airhorner should represent the ideal experience: Blue splash screen with an icon that morphs into the display of the app.
re: Icons - I recommend actually 192px icon or higher.
Regarding the offline-dino flash:
I was using sw-toolbox and performing asynchronous work to setup route handlers at worker startup. This caused an offline dino flash when the application was offline and starting up.
To avoid that, set a sw-toolbox default handler that waits for the asynchronous route handler setup to complete.
var toolbox = require('sw-toolbox');
var setupPromise = someAsyncHandlerSetup()
.then(function () {
// make default handler temporary, allows other fetch handlers (like sw-precache, for example)
toolbox.router.default = null;
});
// until the async handler setup is done, provide a default handler
// to avoid an offline-dino flash when starting up while offline.
toolbox.router.default = function defaultHandler (request) {
return setupPromise.then(function () {
var handler = toolbox.router.match(request);
if (handler) {
return handler(request);
}
throw new Error('default handler could not handle ' + request.url);
});
};
I'm using Cordova 3.5 to build an app which contains a menu with pretty standard items in the list (home, contacts, etc.), and I want to use the native menu icons whenever possible. I believe those icons are already on the device as part of the OS, but I don't know if Cordova gives me a way to reference them.
I suppose I'd need to write a Javascript function to choose the right file name based on the platform, e.g.:
// this is pseudocode
var icon = '';
if (platform === 'android') {
icon = 'some/path/home.png';
} else {
icon = 'other/path/icon.home.png';
// or maybe a function such as the following exists:
// icon = cordova.getNativeIcon('icon.home.png');
}
$('.selector').css('background-image', icon);
Alternatively, I may be able to make do by referencing the files in CSS, e.g.:
.android .home-icon {
background-image: url('some/path/home.png');
}
.ios .home-icon {
background-image: url('other/path/icon.home.png');
}
So, how do folks handle this sort of thing in Cordova? Is there a function I can use to access native icons? Are folks just copying them into their projects? What's the best practice?
If you're working with Cordova, then you'll be working inside a web view provided by the host OS and you won't have direct access to any artwork. I've found that using icon fonts and CSS "themes" to work well enough, but that approach will replicate artwork already provided. There's extra work involved with theming for iOS 6 vs iOS 7 or 8, for example, but it's not as bad as it sounds.
IBM does have an article on partitioning your view between native and web controls, but it sounds a bit cumbersome. More details here: https://www.ibm.com/developerworks/community/blogs/worklight/entry/ios_combining_native_and_web_controls_in_cordova_based_applications
I have set up a small mobile application and during tests I have stumbled upon a problem with older versions of mobile devices running Android version 2. Please note that iPhones, iPads and newer versions of Android, namely 4.xx display the pages well. The problem is as follows:
When page is called directly from the link:
Home
it is properly displayed.
However, when there is a click handler on a link, like here:
$(document).on('click', '#lstAddrList li', function ()
{
var anchor = $(this).find('a');
sessionStorage.SiteAddr = anchor.attr('id');
changePage();
});
the list line (in this case) stays selected and nothing happens. It is ONLY after the calling page is refreshed directly from the browser when the called page is displayed. I have a feeling that older Androids do not properly handle changePage() method.
Will you have some ideas?
I have been trying to create a single codebase for both Iphone & Android for a intermediate level app. ( 4 tabs, multiple windows, maps etc.) using itanium 2.1 API.
However, I have found that things on Android platform dont work as smoothly or willingly as on Iphone epsecially tableviews & UI elemnts. The UI responsiveness on Android is also sluggish.
The kitchen sink examples are pretty straightforward. I am looking at an enterprise ready app which has to be maintained for atleast next couple of years.
Has anybody worked on similar lines with platform quirks and been successful in creating fully functional iOS & Android apps from SAME codebase?
I'm having a lot of success using the compile-time CommonJS mechanism for having a root view that then has os-specific capabilities.
For instance, my os-independent view might be ui/MyView.js :
var createAddButton = require("ui/MyView.AddButton");
var MyView = function() {
var self = Ti.UI.createWindow();
createAddButton(self, function() { alert('ADD!'); });
return self;
};
module.exports = MyView;
Then, I create os-specific functions to handle it:
iphone/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
var addButton = Titanium.UI.createButton({
systemButton: Titanium.UI.iPhone.SystemButton.ADD
});
addButton.addEventListener("click", addHandler);
view.rightNavButton = addButton;
};
android/ui/MyView.AddButton.js
module.exports = function(view, addHandler) {
view.activity.onCreateOptionsMenu = function(e){
var menuItem = e.menu.add({ title: "Add" });
menuItem.addEventListener("click", addHandler);
};
};
The CommonJS system they have implemented will pick the appropriate version of MyView.AddButton.js so that the button is added to the right place. It allows for the majority of the view to be the same, but the os-specific things to be separated properly.
Titanium is not meant for 1 codebase for all. You do need to rewrite stuff for every OS. However, some app developers claim to have reused 95% of its code. So only 5% of the code is OS specific. But I am sure their code is full with if-elses.
What I recommend doing, to be able to maintain it properly, without thousands of if-else constructions, is build a single backend core, and write code specifically for UI related matters per OS. This way, you have some UI related code for Android, UI related code for iOS and 1 core working for both.
Since Android and iOS differ a lot, writing a single codebase will make sure you can never use OS specific features (like android hardware menu button, or iOS NavigationGroup), and will let the UI look non-intuitive.