问题
I am trying to create a button in a Xamarin Forms cross-platform app (iOS and Android), where the button has both text and an image. The XAML is pretty straightforward:
<AbsoluteLayout ...>
<Labels and backgrounds and such>
<Button x:Name="HomeButton2" TranslationX="6" TranslationY="100"
BackgroundColor="#efeff4" TextColor="#4a4a4a"
WidthRequest="58" HeightRequest="76"
ContentLayout="Top,5"
Image="TaskBar_Assets_HomeButtonIcon.png" Text="Home"
Clicked="HomeButton_Clicked" />
</AbsoluteLayout>
but what I get on the iPad is a button where both the image and the text are strangely pushed over to the side:
(the source image "TaskBar_Assets_HomeButtonIcon.png" is 47 x 44 so it should fit fine in the overall button area)
The only way I can find to make this look better, is to make a custom control based on Button, and then I can see that several of the properties of the underlying UIButton seem wonky:
The Control.ImageView.Frame is all zeroes:
Control.ImageView = <UIImageView: 0x12df52940; frame = (0 0; 0 0);
clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO;
layer = <CALayer: 0x173623180>>
The Control.ImageEdgeInsets and .TitleEdgeInsets look odd (the right + left seem like they leave no space for the image or text):
Control.ImageEdgeInsets = {-8.9501953125, 20.33935546875, 8.9501953125, -20.33935546875}
Control.TitleEdgeInsets = {22, -23.5, -22, 23.5}
What I'm doing, is adjusting the Control.ImageEdgeInsets so that Control.ImageEdgeInsets.Left is equal to the half of the (button width minus the image width) and setting Control.ImageEdgeInsets.Right to zero (for no particular reason except that it works)
and then figuring out what to set Control.TitleEdgeInsets was done with trial & error, I ended up with values related to the width of the "Home" text (41 pixels):
Control.ImageEdgeInsets updated to {-8.9501953125, 5.5, 8.9501953125, 0}
Control.TitleEdgeInsets updated to {22, -50, -22, -9}
That results in a reasonable button look:
although it looks like I need to do more trial & error to get the text "Home" actually centered.
But why do I need to go through all this? Why doesn't the button just display text & image correctly in the first place?
And if I do have to go through all this, why are the values for Left & Right for ImageEdgeInsets and TitleEdgeInsets so different?
回答1:
Most of the articles I have read about images on buttons suggest constructing your own using an Image and a Label in a grid using a gesture recognizer to handle the tap.
You could also try a button and an image in a grid.
Use Margin to adjust placement.
I try and stay clear of absolute layout.
回答2:
Here's the ButtonRenderer source code from Xamarin.Froms.If you set the ContentLayout to Top
, the below codes will be run:
void ComputeEdgeInsets(UIButton button, Button.ButtonContentLayout layout)
{
...
var horizontalImageOffset = labelWidth / 2;
var horizontalTitleOffset = imageWidth / 2;
...
button.ImageEdgeInsets = new UIEdgeInsets(-imageVertOffset, horizontalImageOffset, imageVertOffset, -horizontalImageOffset);
button.TitleEdgeInsets = new UIEdgeInsets(titleVertOffset, -horizontalTitleOffset, -titleVertOffset, horizontalTitleOffset);
}
As the codes show, the Left offset of image is horizontalImageOffset
which is labelWidth / 2
. The Left offset of title is horizontalTitleOffset
which is imageWidth / 2
.
So, when the text is wider, the left offset of image will be bigger. When the image is wider, the left offset of text will be bigger.
Edit:
In native iOS, the default layout is like the left image: Image is at left and Label is at right. In Xamarin for Top
setting, Xamarin moves the Image up and right, moves the Label down and left to makes them like the right image. I paint this illustration, hope it clear.
来源:https://stackoverflow.com/questions/46779907/xamarin-button-with-text-and-image-in-absolute-layout-results-in-mis-aligned-e