I am using 'ScaleTo' property for showing little animation in the screen, It work's greatly in xamarin.Ios but in android not works good. What I am tried is I have taking two images and each 30000 sec I am replace with other image.
Here is the sample code:
Private async void SampleAnimation()
{
TestImage.Source = "ImageOne.png";
await TestImage.ScaleTo(1.1, 3000, Easing.Linear);
await TestImage.ScaleTo(1, 2);
TestImage.Source = "Imagetwo.png";
await TestImage.ScaleTo(1.1, 3000, Easing.Linear);
await TestImage.ScaleTo(1, 2);
RepeatLoop();
}
private async void RepeatLoop()
{
await SampleAnimation();
}
In my xaml page image is added and in behind code load background image method is called in constructor. What my problem is after completion of first image animation, fliping the screen with white, white screen is appeared little amount of time between image inserting from imageone to imagetwo but it work's in ios without any problem, Only I am getting issue in andorid. Please suggest any idea upon this.
Related
I need to capture the screen of my App in iPhone. Whenever there is a pop up page to be captured, only the pop up view is visible in the screenshot, the background screen goes black in the screenshot captured. I need the screenshot to show the pop up along with the underlying page.
I am coding in Xamarin.Forms. I am using DependencyService to capture screenshot in iOS and Android.
In Android I am able to capture popup along with background page.
But in iOS the popup along with a black background is captured.
var capture = UIScreen.MainScreen.Capture();
This is the code in iOS DependencyService to capture screenshot.
I had a screenshot method that I used in one of my POC's but I am not sure if it will work with the pop-up thing or not you can try it out
private void TakeScreenshot()
{
var layer = UIApplication.SharedApplication?.KeyWindow?.Layer;
var scale = UIScreen.MainScreen.Scale;
UIGraphics.BeginImageContextWithOptions(layer.Frame.Size, false, scale);
var context = UIGraphics.GetCurrentContext();
if (context == null)
{
return; // Show popup screenshot was not taken
}
layer.RenderInContext(context);
var screenshotImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
if (screenshotImage != null)
{
screenshotImage.SaveToPhotosAlbum((UIImage, NSError) => { });
}
}
I'm currently developing a mobile application with JavaFX, using GluonHQ and JavaFXPorts. One of my screens contains a listview as you can see from the screenshot below, which was taken from my iPhone 6.
I have noticed the following problems with the scrollbar in mobile devices:
The first time i touch the screen the scroll bar appears a bit off place and then moves to the correct right position. This just happens quickly only the first time. (Screenshot)
I noticed that the scrollbar appears every time i touch the screen and not only when I touch and drag. On native iOS applications the scrollbar appears only when you touch and drag. If you keep your finger on screen and then remove it the scrollbar does not appear.
The scrollbar always takes some time to disappear when I remove my finger from the screen, whilst in native apps it disappears instantly.
Can anyone help me on fixing these issues. How can you define the time the scrollbar appears before it hides again?
You can experience this situation by just creating a ListView and load it with some items.
UPDATE
Thanks to the answer of Jose Pereda below, I have managed to overcome all three problems described above. Here is the code I used to reach the desired results. Watch this short video to get a quick idea of how the new scrolling bar appears and behaves. Again, Jose, you are the boss! Please go ahead with any comments for improvement.
public class ScrollBarView {
public static void changeView(ListView<?> listView) {
listView.skinProperty().addListener(new ChangeListener<Object>() {
private StackPane thumb;
private ScrollBar scrollBar;
boolean touchReleased = true, inertia = false;
#Override
public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
scrollBar = (ScrollBar) listView.lookup(".scroll-bar");
// "hide" thumb as soon as the scroll ends
listView.setOnScrollFinished(e -> {
if (thumb != null) {
touchReleased = true;
playAnimation();
} // if
});
// Fix for 1. When user touches first time, the bar is set invisible so that user cannot see it is
// placed in the wrong position.
listView.setOnTouchPressed(e -> {
if (thumb == null) {
thumb = (StackPane) scrollBar.lookup(".thumb");
thumb.setOpacity(0);
initHideBarAnimation();
} // if
});
// Try to play animation whenever an inertia scroll takes place
listView.addEventFilter(ScrollEvent.SCROLL, e -> {
inertia = e.isInertia();
playAnimation();
});
// As soon as the scrolling starts the thumb become visible.
listView.setOnScrollStarted(e -> {
sbTouchTimeline.stop();
thumb.setOpacity(1);
touchReleased = false;
});
} // changed
private Timeline sbTouchTimeline;
private KeyFrame sbTouchKF1, sbTouchKF2;
// Initialize the animation that hides the thumb when no scrolling takes place.
private void initHideBarAnimation() {
if (sbTouchTimeline == null) {
sbTouchTimeline = new Timeline();
sbTouchKF1 = new KeyFrame(Duration.millis(50), new KeyValue(thumb.opacityProperty(), 1));
sbTouchKF2 = new KeyFrame(Duration.millis(200), (e) -> inertia = false, new KeyValue(thumb.opacityProperty(), 0));
sbTouchTimeline.getKeyFrames().addAll(sbTouchKF1, sbTouchKF2);
} // if
} // initHideBarAnimation
// Play animation whenever touch is released, and when an inertia scroll is running but thumb reached its bounds.
private void playAnimation() {
if(touchReleased)
if(!inertia || (scrollBar.getValue() != 0.0 && scrollBar.getValue() != 1))
sbTouchTimeline.playFromStart();
} // playAnimation()
});
} // changeView
} // ScrollBarView
As mentioned in the comments, the first issue is known, and for now it hasn't been fixed. The problem seems to be related to the initial width of the scrollbar (20 pixels as in desktop), and then is set to 8 pixels (as in touch enabled devices), and moved to its final position with this visible shift of 12 pixels to the right.
As for the second and third issues, if you don't want to patch and build the JDK yourself, it is possible to override the default behavior, as the ScrollBar control is part of the VirtualFlow control of a ListView, and both can be found on runtime via lookups.
Once you have the control, you can play with its visibility according to your needs. The only problem with this property is that it is already bound and constantly called from the layoutChildren method.
This is quite a hacky solution, but it works for both 2) and 3):
public class BasicView extends View {
private final ListView<String> listView;
private ScrollBar scrollbar;
private StackPane thumb;
public BasicView(String name) {
super(name);
listView = new ListView<>();
// add your items
final InvalidationListener skinListener = new InvalidationListener() {
#Override
public void invalidated(Observable observable) {
if (listView.getSkin() != null) {
listView.skinProperty().removeListener(this);
scrollbar = (ScrollBar) listView.lookup(".scroll-bar");
listView.setOnScrollFinished(e -> {
if (thumb != null) {
// "hide" thumb as soon as scroll/drag ends
thumb.setStyle("-fx-background-color: transparent;");
}
});
listView.setOnScrollStarted(e -> {
if (thumb == null) {
thumb = (StackPane) scrollbar.lookup(".thumb");
}
if (thumb != null) {
// "show" thumb again only when scroll/drag starts
thumb.setStyle("-fx-background-color: #898989;");
}
});
}
}
};
listView.skinProperty().addListener(skinListener);
setCenter(listView);
}
}
I have added a popup window to my main UI as follows:
Window component = new Window();
UI.getCurrent().addWindow(component);
Now, I want my popup to be centered horizontally and e.g. 40 pixels from the top of the screen. As far as I can see Vaadin has 4 methods for positioning my window.
component.center()
component.setPosition(x, y)
component.setPositionX(x)
component.setPositionY(y)
None of these are really what I want. I was hoping at first that setPositionY might help me. This does allow me to get the right distance from the top, but the x-position is now set to 0, where I wanted it to be centered.
The setPosition might have helped if I was able to calculate what the x-position should be, but this would require me to know the width of the component in pixels, but component.getWidth just tells me 100%.
Next I tried to use CSS styling on the component, writing and explicit css rule and adding it to the component with addStyleName. It seems though that Vaadin overrides whatever I wrote in my css with its own defaults...
Any ideas how to get my Window component positioned correctly?
I used the methods getBrowserWindowWidth() and getBrowserWindowHeight() from the com.vaadin.server.Page class for this.
I centered my "log" window horizontally in the lower part of the browser window with
myWindow.setHeight("30%");
myWindow.setWidth("96%");
myWindow.setPosition(
(int) (Page.getCurrent().getBrowserWindowWidth() * 0.02),
(int) (Page.getCurrent().getBrowserWindowHeight() * 0.65)
);
Solution 1: Use SizeReporter
Indeed, setPositionY() will reset the window's centered property to false. As the width of your pop-up and that of your browser window are not know before they appear on the screen, the only way I know to get those values is to use the SizeReporter add-on. Its use is quite straightforward:
public class MyUI extends UI {
private Window popUp;
private SizeReporter popUpSizeReporter;
private SizeReporter windowSizeReporter;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
addWindow(popUp);
popUpSizeReporter = new SizeReporter(popUp);
popUpSizeReporter.addResizeListenerOnce(this::centerPopUp);
windowSizeReporter = new SizeReporter(this);
windowSizeReporter.addResizeListenerOnce(this::centerPopUp);
}
private void centerPopUp(ComponentResizeEvent event) {
int popUpWidth = popUpSizeReporter.getWidth();
int windowWidth = windowSizeReporter.getWidth();
if (popUpWidth == -1 || windowWidth == -1) {
return;
}
popUp.setPositionX((windowWidth - popUpWidth) / 2);
}
}
This piece of code will be okay as long as you don't resize the pop-up. If you do, it will not be automatically recentered. If you replace addResizeListenerOnce() by addResizeListener() then it will automatically recenter the pop-up but you'll get some "UI glitches" as the add-on sends resize events almost continually while you're resizing your pop-up...
You could try to do it using CSS, but I personally avoid CSS as much as I can with Vaadin :).
You'll need to recompile the widgetset after you've added the add-on as a dependency.
Solution 2: Use com.vaadin.ui.JavaScript
I won't vouch for the portability of this solution but I guess it will work on most modern browsers.
public class MyUI extends UI {
private Window popUp;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
popUp.addStyleName("window-center");
addWindow(popUp);
// Add a JS function that can be called from the client.
JavaScript.getCurrent().addFunction("centerWindow", args -> {
popUp.setPositionX((int) ((args.getNumber(1) - args.getNumber(0)) / 2));
});
// Execute the function now. In real code you might want to execute the function just after the window is displayed, probably in your enter() method.
JavaScript.getCurrent().execute("centerWindow(document.getElementsByClassName('window-center')[0].offsetWidth, window.innerWidth)");
}
}
I am using React Native's Navigator to navigate through scenes in iOS app. I found that although I can swipe back to previous screen by swiping from left edge to right, it looks like the region that I can swipe is not as big or responsive as the native navigation. Sometimes I swipe a little off the edge and it doesn't work.
I am wondering if there is a way to apply some tuning to this area, i.e. make the swipe go back area a little bigger so user have better success rate.
It may not be the best solution but you can change the edgeHitWidth in NavigatorSceneConfigs.js
The default for 'left-to-right' is 30
This will affect your entire project and every time you upgrade react native you will need to make these changes again.
Don't know if it still can help but :
const SCREEN_WIDTH = require('Dimensions').get('window').width;
const buildStyleInterpolator = require('buildStyleInterpolator');
const BaseSceneConfig = Navigator.SceneConfigs.HorizontalSwipeJump;
const CustomBackGesture = Object.assign({}, BaseSceneConfig.gestures.jumpBack, {
// Make it so we can drag anywhere on the screen
edgeHitWidth: SCREEN_WIDTH,
});
const CustomForwardGesture = Object.assign({}, BaseSceneConfig.gestures.jumpForward, {
// Make it so we can drag anywhere on the screen
edgeHitWidth: SCREEN_WIDTH,
});
const CustomSceneConfig = Object.assign({}, BaseSceneConfig, {
// A very tighly wound spring will make this transition fast
springTension: 100,
springFriction: 1,
gestures: {
jumpBack: CustomBackGesture,
jumpForward: CustomForwardGesture,
},
});
you can customize gesture and edgeHitWidth: SCREEN_WIDTH does the trick.
My application have one screen below the detail of that. Screen name EventList . This screen have designed full. There are two ButtonField Next and Previous . At the bottom of these two Button ListField is placed in this screen.
When i click on Next or Previous my ListField will update . It is updated successfully using updateListField() method which is created in this screen. All is working fine up to this. But my concern is that when i click on these Button ListField will take time (around 3 or 4 second)to update new data. During my data updating in background i want to show Massage like Please wait.../Loading.... How can i show this without using PopupScreen.
i had tried the below code but not working properly.
VerticalFieldManager manager = new VerticalFieldManager();
manager.add(new LabelField("Please Wait..."));
Screen popup = new PopupScreen(manager);
If i will done this using PopupScreen my full logic will be change for that screen and it will time consuming task.
Please suggest me how can we add FieldManager on existing MainScreen.
Thanks in Advance !!!
The MainScreen class includes a status field that you can use for this. In your class extending MainScreen add:
setStatus(new LabelField("Please wait..."));
to remove that status:
setStatus(null);
However, you need to do this on the event thread and then return so the OS can update the user interface. If you are performing the update of your list on the event thread (the thread that will call your code when the button is pressed) then you should perform that work on a spearate thread and use UiApplication.invokeLater() or hold the event lock to perform updates on the user interface.
Application.getApplication().invokeLater(
new Runnable() {
public void run() {
GIFEncodedImage image;
EncodedImage encodedImage = EncodedImage
.getEncodedImageResource("spiral.gif");
byte data[] = new byte[3000];
data = encodedImage.getData();
image = (GIFEncodedImage) EncodedImage
.createEncodedImage(
data, 0,
data.length);
AnimatedGIFField animatedGIF = new AnimatedGIFField(
image);
PopupScreen popup = new PopupScreen(
new VerticalFieldManager());
popup.add(animatedGIF);
Border border = BorderFactory
.createSimpleBorder(
new XYEdges(),
Border.STYLE_SOLID);
popup.setBorder(border);
UiApplication
.getUiApplication()
.pushScreen(popup);
Timer timer = new Timer();
timer.schedule(new CountDown(),
3000);
}
});