(I posted this initially on the Xamarin Forums, but then decided I might get a faster answer here?)
TL;DR: Some layouts will count a tap on a transparent background, others won't. Setting InputTransparent on a container sets it for all of its children, and I feel like children should be able to override the parent. I need to create elements that overlay another element and pass taps through a transparent region but still have tappable buttons. When I try this with a Grid, it doesn't work. I don't want to go back to AbsoluteLayouts. I'm mostly working in iOS right now, I'm not quite sure if it's a problem in Android yet. Windows Phone/UWP isn't on the table.
Longer version:
I'm rewriting some layouts that worked OK in an older Xamarin Forms (1.3 I think). We recently upgraded to 2.1, and it wreaked havoc on the layout code's bad decisions. I'm tasked with updating the layouts to behave themselves. While I recognize 2.2 has been released, I just tried an upgrade and everything I'm typing seems true in that version as well, so it's not a 2.1 vs. 2.2 issue, or at least if some improvements are made they aren't helping me.
It's a mapping application, so the centerpiece of all layouts is an expensive, temperamental OpenGL element. This element very much does not like to be reparented, so I've adopted a layout sort of like this imaginary XAML:
<ContentPage>
<CustomLayout>
<OurHeaderControl />
<TheMapControl />
<OurFooterControl />
<MapOverlay />
</CustomLayout>
</ContentPage
The purpose of "MapOverlay" is to implement our workflows by adding Xamarin elements on top of the header/footer areas and/or the map. For example, one layout adds a list of directions to the bottom above the footer, so it has less room for the map to appear. The custom layout understands this and lays out the map after the overlay so it can ask for the correct map bounds.
In this layout, I cannot tap on anything the MapOverlay is over. I can make it InputTransparent and tap those things, but then all of its children are also not tappable. This was not true in the old layouts.
Here's the only differences I see between the old layouts and the new:
The old layouts were a complicated mess of AbsoluteLayouts. It looked something like this, I didn't write it:
<ContentPage>
<AbsoluteLayout> // "main layout"
<AbsoluteLayout> // "map layout"
<Map /> // An AbsoluteLayout containing the OpenGL view.
</AbsoluteLayout>
<AbsoluteLayout> // "child layout"
<SubPage /> // An AbsoluteLayout
</AbsoluteLayout>
</AbsoluteLayout>
</ContentPage>
The main layout contains AbsoluteLayouts to constrain the child views. One child view is itself an AbsoluteLayout that contains the Map and a handful of other elements associated with it. The other child is the overlay, which is always an AbsoluteLayout that contains the elements relevant to that overlay. These layouts all reference each other in cycles and update each other as layout events change. It's a fascinating ping-ponging that eventually settles down. Usually. Sometimes things just disapper. Obviously there's a reason I'm rewriting it.
But I can click on what I need to click on at every layer, and I don't get that.
So, let's talk about what I need to work, and maybe figure out if it's a bug why it's not working, or if it's a coincidence that it worked with other layouts. Here's a non-XAML page layout that demonstrates, my project's got its roots in the days when you couldn't use XAML in shared libraries:
I need to be able to tap both buttons in this UI and have them respond.
public class MyPage : ContentPage {
public MyPage() {
var mainLayout = new AbsoluteLayout();
// Two buttons will be overlaid.
var overlaidButton = new Button() {
Text = "Overlaid",
Command = new Command((o) => DisplayAlert("Upper!", "Overlaid button.", "Ah."))
};
mainLayout.Children.Add(overlaidButton, new Rectangle(0.25, 0.25, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), AbsoluteLayoutFlags.PositionProportional);
// The top overlay layout will be a grid.
var overlay = new Grid() {
RowDefinitions = { new RowDefinition() { Height = new GridLength(1.0, GridUnitType.Star) } },
ColumnDefinitions = {
new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Star) },
new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Star) },
},
BackgroundColor = Color.Transparent
};
var overlayingButton = new Button() {
Text = "Overlaying",
Command = new Command((o) => DisplayAlert("Upper!", "Overlaying button.", "Ah."))
};
overlay.Children.Add(overlayingButton, 0, 1);
mainLayout.Children.Add(overlay, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All);
// This pair of property sets makes the overlaid button clickable, but not the overlaying!
// overlay.InputTransparent = true;
// upperOverlayButton.InputTransparent = false;
Content = mainLayout;
}
}
This only lets me tap the "overlaying" button even when I change the Grid to an AbsoluteLayout.
I'm stumped. It took me 2 weeks to debug the initial layouts and come up with a new solution. I really don't want to disassemble all of our layouts and put everything in one big AbsoluteLayout or a custom layout. In WPF, there were two kinds of transparent: "transparent background" meant the background could still hit test, and "null background" meant the background would not hit test. Is there some way to overlay layouts in Xamarin like this?
Or, more appropriate, why is the convoluted nest of numerous AbsoluteLayouts in our old layouts working like I need it to, but this much simpler layout isn't?
updates
Here's some additional information I remembered:
This behavior is iOS specific. On Android, both the example code and our code work.
I'm not the first person to have this problem: On StackOverflow. On Xamarin's Forums.
In general it seems as if the behavior with iOS in regards to how InputTransparent is being handled in a Grid compared to the other two platforms. I'm not particularly certain whether I'd quantify the current behavior as a bug at this time, but I understand that it's frustrating to run into a disparity in platform behavior.
There is a fix of sorts for your situation, though, if I'm understanding it correctly. It appears similar a similar report was filed before and behavior regarding iOS was mentioned via this SO link. The question is posed in the scope of a non-Forms iOS app, but the logic can be applied here.
By using a custom renderer (let's use a CustomGrid as an example), you can specifically implement the iOS implementation of the Grid to follow the aforementioned link's manner of finding underlying views:
CustomGrid.cs (PCL):
public class CustomGrid : Grid
{
public CustomGrid() { }
}
CustomGrid.cs (iOS):
[assembly: ExportRenderer(typeof(CustomGrid), typeof(CustomGridRenderer))]
public class CustomGridRenderer : ViewRenderer
{
public override UIKit.UIView HitTest(CoreGraphics.CGPoint point, UIKit.UIEvent uievent)
{
UIView hitView = base.HitTest(point, uievent);
if (hitView == this)
{
return null;
}
return hitView;
}
}
In this manner you should not explicitly set InputTransparent for iOS, and any taps on the Grid itself are sent through to anything below. Since Android works with InputTransparent, though, in this particular case you can wrap that inside a Device.OnPlatform statement and skip implementing the Android custom renderer if you don't want to:
Device.OnPlatform(Android: () =>
{
overlay.InputTransparent = true
});
Using your above code modified to use the CustomGrid and iOS renderer, I'm able to tap both buttons.
I've fouded this plugin to get the Immersive Android view on a Hybrid app (GitHub)
But the navbar is attached into the StatusBar
i've tried with css ..
.platform-android.has-translucent-status-bar.app-header-bar{ padding-top:25px!important; }
Any suggestion?
If you want to completely hide the status bar:
$ionicPlatform.showStatusBar(false);
Make sure to inject $ionicPlatform to the service/controller. Also make sure to install the Cordova Statusbar Plugin.
ionic plugin add cordova-plugin-statusbar
If you only want to push the content down a bit, you can do this:
body {
padding-top: 25px !important;
}
I have a project since today. I have an ionic project who comes from a Windows and I can't scroll the view in my web browser.
But when I create a project in Mac OSX I can scroll like a charm with maintaining my left click mouse and scroll (like it would be tactile).
So can someone help me to make this new project scrollable in Mac OSX please ?
Many thanks.
I have added to my ionic projects that do not need Cordova plugins the platform "Browser" to be able to deploy rapidly a nice webapp.
I faced the same issue and had to add this CSS property :
.isBrowserView {
overflow-y: auto !important;
}
On my app.run(), I have add the following code :
var deviceInformation = ionic.Platform.device();
if (deviceInformation.platform === "browser"){
$rootScope.isBrowser = true;
}else{
$rootScope.isBrowser = false;
}
Finally, I add this ng-class condition on my ion-contents
<ion-content ng-class="{ isBrowserView : isBrowser== true } ">
i'm having problems to see the bottom bar icons on a Sencha Touch app.
I'm using compass and scss to style the app.
Actually, after a research i'm using the mixing:
#include pictos-iconmask('home');
to import the icons that are used in the tabbar.
The bar elements are defined i that way:
{
title: 'FAQ',
iconCls: 'star'
},
And seems to be well-defined, in Safari the inspector shows the
-webkit-mask-image:theme_image("default", "pictos/home.png"); property but this is strikethrough. In Chrome the property doesn't appear, what could be the cause of that issue?
The attached image shows both scenarios, at the top Safari and the property that i mentioned. At bottom the bar without the "broken" placeholder that Safari shows.
I found a solution that increments the icons z-index property, but i tried this with no luck.
The workaround is like this:
.x-tabbar > * {
z-index: 999 !important;
}
Any help is appreciated!
EDIT 1: Someone have any idea?
In Sencha Touch 2.4.x you need to do the following :
Install Rub
Compass
Navigate into the app home folder (i.e. to the level of the index.html file)
In Terminal run sencha app watch
Open the resources/sass/app.scss and add the following code:
// This is different in 2.4.x. In earlier versions it was pictos-iconmask as you've indicated you tried in the question.
#include icon('browser');
Your tab panel item should have the iconCls set up like so:
{
.....,
title: 'Favorites',
iconCls: 'heart'
}
Additional (Optional) Step:
Sometimes the iconCls has been commented out in the framework (this has happened to me once before). In that case, go to AppName/touch/resources/themes/stylesheets/sencha-touch/base/mixins/_Class.scss
Search in the file for a line of code that reads :
#else if ($name == "star") { #return "S"; }
Uncomment the line if it's been commented.
I need to add a background image to a button in Titanium studio (version 3.1.1). I tried almost everything I can think of but still the button image does not show up. Image file path is correct. I cleaned the project, restarted titanium still not working. I had the same problem when I was trying to add window background image, it didn't show up and suddenly it appeared without even changing a line of code. How can I fix this?
var pauseResumeButton = Titanium.UI.createButton({
title:"play",
top:'70%',
width:80,
height:80,
backgroundColor:'green',
backgroundImage:"/graphics/play.png",
});
Try the following code
var pauseResumeButton = Titanium.UI.createButton({
title:"play",
top:'70%',
width:80,
height:80,
backgroundColor:'green',
backgroundImage:"graphics/play.png",
});
Also please refer this answer
Try to change your button's background to transparent like that:
var pauseResumeButton = Titanium.UI.createButton({
title:"play",
top:'70%',
width:80,
height:80,
backgroundColor:'transparent',
backgroundImage:"graphics/play.png",
})
win.add( pauseResumeButton )