Gluon Mobile Dialog Appbar Customization - gluon-mobile

I have a Settings View with a styled AppBar and when I open a full screen dialog from that View, the AppBar styling follows the global swatch specified.
THEN, when I close the dialog box, the Settings View AppBar retains the dialog styling (it should have a white background, but it's green which is the swatch that is specified for the application).
Further Clarification:
The View is a page for Settings and then when you click each setting a dialog pops up with the content set to StackPanes that contain information for that specific setting.
I have tried to add a method that stylizes the AppBar on Dialog close, hide, and hidden event handlers:
public void initView(SettingView viewType) {
View pane = null;
try {
switch (viewType) {
case PASSWORD_CHANGE:
pane = getPasswordPane();
break;
case PROFILE_CHANGE:
pane = getProfilePane();
break;
case BANK_CHANGE:
pane = getBankPane();
break;
case NOTIFICATION_CHANGE:
pane = getNotificationPane();
break;
}
} catch (IOException e) {
System.out.println("IOException: " + e);
}
//this.settingsContainer = new Dialog(true);
this.settingsContainer.setContent(pane);
MobileApplication.getInstance().removeLayerFactory("$$$DropdownButtonSkin$$$");
Platform.runLater(new Runnable() {
#Override
public void run() { //None of these change the appbar styling
settingsContainer.setOnShowing(e -> { setAppBar("Settings");});
settingsContainer.setOnShown(e -> { setAppBar("Settings");});
settingsContainer.setOnHiding(e -> { setAppBar("Settings");});
settingsContainer.setOnHidden(e -> { setAppBar("Settings");});
//When closing the appbar the color remains to the swatch instead of the customized background
settingsContainer.setOnCloseRequest(e -> { setAppBar("Settings");});
settingsContainer.showAndWait();
}
});
}
public AppBar setAppBar(String name) {
Button menu = MaterialDesignIcon.MENU.button();
menu.setStyle("-fx-text-fill:darkgreen;");
menu.setOnMouseClicked(e -> {
MobileApplication.getInstance().showLayer(Appstar.MENU_LAYER);
});
AppBar appBar = MobileApplication.getInstance().getAppBar();
appBar.clear();
appBar.setNavIcon(menu);
appBar.setTitleText(name);
appBar.setVisible(true);
appBar.setBackground(new Background(new BackgroundFill(Color.WHITE, new CornerRadii(0), new Insets(0, 0, 0, 0))));
return appBar;
}

Considering that you want the same app-bar color on all views (i.e. white in all the views), the easiest way to solve this is to use CSS.
You can set the color of the AppBar on a full-screen dialog by using the custom style-class for the AppBar on a full-screen dialog i.e. dialog-fullscreen along with the base style-class app-bar. Therefore, you can use something like this:
.app-bar.dialog-fullscreen {
-fx-background-color: green; // OR -primary-swatch-500;
}
For setting the overall app-bar color to white, you can simply use:
.app-bar {
-fx-background-color: white;
}

Related

Shadow in UIView cannot overlay Entry or Editor or Picker in Xamarin Forms

I added an RoutingEffect in Xamarin Form project and PlatformEffect in my Xamarin.iOS project. It will add effect to Stacklayout. The Stacklayout in this demo is a custom navigation bar. The below of navigation bar is a scrollview has many cells (label, entry, picker).
I implemented in Android is OK.
But in iOS has problem: Shadow effect cannot overlays some controls, such as: Entry, Editor, Picker. Could you share me how to fix it?
This is code in Xamarin.iOS project.
public class DropShadowEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
var effect = (myDemo.UIControls.DropShadowEffect)Element.Effects.FirstOrDefault(e => e is myDemo.UIControls.DropShadowEffect);
if (effect != null)
{
Container.Layer.CornerRadius = effect.Radius;
Container.Layer.ShadowColor = UIColor.Red.CGColor;// effect.Color.ToCGColor();
Container.Layer.ShadowOffset = new CGSize(effect.DistanceX, effect.DistanceY);
Container.Layer.ShadowOpacity = 0.8f;
Container.Layer.ShadowRadius = 2f;
Container.Layer.ShouldRasterize = true;
Container.Layer.MasksToBounds = false;
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot set property on attached control. Error: {0}", ex.Message);
}
}
*Shadow effect overly Label is OK
*Shadow effect cannot overlay either Picker or Entry
Cause:
Actually, such as Label will still overlay the shadow.But it doesn't seem obvious.If you set the background of label (such as red ),you will see the overlay.
Solution:
You can set the BackgroundColor of the Picker and Entry in the custom renderer to let the alpha as 0.
For example in EntryRenderer
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BackgroundColor = new UIColor(1,1,1,0);//The last parameter sets the alpha of backgound as transparent
Control.Layer.MasksToBounds = true;
Control.Layer.CornerRadius = xxx; //set the rounded corner
Control.Layer.BorderColor = UIColor.xxx.CGColor;
Control.Layer.BorderWidth = xxx;
}
}

How to remove the background of a dialog?

I created a custom dialog with my own panes and controls in it. But the dialog has a white border default which I want to remove. Here is an example with a single image:
I tried using ScenicView but couldn't find a way to catch the dialog layer and modify it:
public class MainView extends View {
Image img = new Image("https://i.stack.imgur.com/7bI1Y.jpg", 300, 500, true, true);
public MainView(String name) {
super(name);
Button b = new Button("Pop");
b.setOnAction(e -> {
Dialog<Void> dialog = new Dialog<>();
dialog.setOnShown(e2 -> {
Parent parent = getParent();
Pane p = (Pane) parent.lookup(".dialog");
p.setPadding(new Insets(0));
});
dialog.setGraphic(new ImageView(img));
dialog.showAndWait();
});
setCenter(b);
}
}
Best i got was removing the flowpane child to remove some of the lower part
dialog.setOnShown(e2 -> {
Parent parent = getParent();
Pane p = (Pane) parent.lookup(".dialog");
p.getChildren().removeIf(c -> (c instanceof FlowPane));
System.out.println(p.getChildren());
});
Removing the VBox moves the dialog which i don't want to do and changing its padding also dose nothing.
As you can see with ScenicView, the Dialog has the dialog style class.
One easy way to modify the dialog style is via css. Just add a css file to your view, and set:
.dialog {
-fx-background-color: transparent;
}
That will set the background transparent, instead of the default white color.
If you want to remove the borders instead, then you can play with padding. As you can also see with ScenicView, the dialog has a VBox with style class container for the content in the center, and the flow pane for the buttons at the bottom, with style class dialog-button-bar.
Before anything, just use the setContent method to add the image instead of the setGraphic one:
dialog.setContent(new ImageView(img));
And this will be required to remove all the borders, and let the image take the whole dialog:
.dialog,
.dialog > .container,
.dialog > .dialog-button-bar {
-fx-padding: 0;
}

IOS Tabs Title without icons white space on the top

I a have page with tabs, in the tabs i only want text, in android the text is centered both vertically and horizontally, without any white spaces, but in the ios version there is a white space on the top of the text, because there isnt icons.
How can i remove the white space on the top?
You can use a custom renderer for that:
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabBarRenderer))]
namespace MyProject.iOS.Renderers
{
public class CustomTabBarRenderer : TabbedRenderer
{
public override void ViewWillAppear(bool animated)
{
if (TabBar?.Items == null)
return;
// Go through our elements and change them
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
UpdateTabBarItem(TabBar.Items[i]);
}
base.ViewWillAppear(animated);
}
private void UpdateTabBarItem(UITabBarItem item)
{
if (item == null)
return;
// Set the font for the title.
item.SetTitleTextAttributes(new UITextAttributes() { Font = UIFont.FromName("Your-Font", 10) }, UIControlState.Normal);
item.SetTitleTextAttributes(new UITextAttributes() { Font = UIFont.FromName("Your-Font", 10) }, UIControlState.Selected);
// Moves the titles up just a bit.
item.TitlePositionAdjustment = new UIOffset(0, -2);
}
}
}
The TitlePositionAdjustment is what you're looking for. You can also use this to change the font size if needed using the SetTitleTextAttributes method.

JavaFXPorts - Problems with ScrollBar on Mobile Devices

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);
}
}

Android: Make multiline edittext scrollable, disable in vertical scroll view

I am developing an application in which i am struct at a point.
As according to my application requirement i created horizontal scrollview in xml and then vertical scrollview in .java as :
// Vertical Scroll view in Linear layout
ScrollView scrollView = new ScrollView(this);
scrollView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
Then i created a table view programatically and added it in scrollview. I created multiline edit text and disable it because i want to set text in it run time and added this in table view as a row..
EditText editText = new EditText(this);
editText.setId(1);
editText.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,0f));
editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
editText.setGravity(Gravity.TOP|Gravity.LEFT);
editText.setHint("Comment");
editText.setSingleLine(false);
editText.setLines(5);
editText.setMaxLines(5);
editText.setText(CommentFromDB);
editText.setEnabled(false);
tableLayout.addView(editText);
// Add table in Horizontal scroll view
scrollView.addView(tableLayout);
Now i want to make edit text scrollable which i achieve by code:
editText.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if (view.getId() == 1) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()&MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_UP:
view.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_DOWN:
view.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return false;
}
});
But the edittext is not scrolling easily. I need the smooth scrolling.
How to do that please guide me.
You can do one thing.
Just make edit text focusable false. And apply on touch listener.
So user is not able to edit text and it will scroll as:
EditText editText = new EditText(this);
editText.setId(1);
editText.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,0f));
editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
editText.setGravity(Gravity.TOP|Gravity.LEFT);
editText.setHint("Comment");
editText.setSingleLine(false);
editText.setLines(5);
editText.setMaxLines(5);
editText.setText(CommentFromDB);
editTextRemark.setFocusable(false);
Apply onTouchListner as:
editTextRemark.setOnTouchListener(touchListener);
and
OnTouchListener touchListener = new View.OnTouchListener(){
public boolean onTouch(final View v, final MotionEvent motionEvent){
if(v.getId() == 1){
v.getParent().requestDisallowInterceptTouchEvent(true);
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_UP:
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return false;
}
};
Hope this answer will help you.
EditText editText = findViewById(R.id.editText);
editText.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
// TODO Auto-generated method stub
if (view.getId() ==R.id.common_remark) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch (event.getAction()&MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_UP:
view.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
}
return false;
}
});
And in xml add this line in EditText:
android:scrollbars = "vertical"
add to EditText
android:inputType="textMultiLine"
in kotlin use this
editText.setOnTouchListener { v, event ->
v.parent.requestDisallowInterceptTouchEvent(true)
when (event.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_UP -> v.parent.requestDisallowInterceptTouchEvent(false)
}
false
}

Resources