I'm trying to build a tabbar in corona only using custom graphics for up/down states, and background. I find that corona adds left and right padding as the attached image & basic setup below shows. The images are both 32x32 and should fill the space exactly, instead there are black lines at either end and the buttons are forced to overlap.
I've tried every option available in the docs but with no success. Does anyone know if there's an undocumented option that overrides the automatic positioning of tabbar buttons?
-- table to setup buttons
local tabButtons = {
{ up="icon1.png", down="icon1-down.png", width = 32, height = 32, cornerRadius=0, onPress=onFirstView, selected=true },
{ up="icon2.png", down="icon2-down.png", width = 32, height = 32, cornerRadius=0, onPress=onSecondView },
}
-- create the actual tabBar widget
local tabBar = widget.newTabBar{
width=64, height=32,
buttons = tabButtons
}
Here's the output:
This is a known bug and is being addressed.
Related
I was wondering how I can get a gap between overlaying views in swift. This is really hard for me to explain so I added a couple images to explain what I'm talking about This is the effect in iMessage The same effect in Facebook Messenger And again in facebook messenger. I am talking about the little gap of space in between the view that says the number of minutes and the profile image (in the 3rd image). I was wondering how I could achieve the same thing in Swift because I'd like to integrate this into my app. Thank you so much!
You can do this many ways.
One of the way, I am posting.
One View, UIView, that should be Square. Inside that, One UIImageView and One SmallView
Constraints as follows:
OuterView: width & height be 120, top 50, and Center Horizontally
ImageView = { 4,4,4,4 },
SmallView = right and bottom as 0, width and height be 40 [Square]
PlusSignImgVw = { 4,4,4,4 }
Like below:
Coding:
override func viewDidAppear(_ animated: Bool) {
imageVw.layer.cornerRadius = imageVw.frame.size.width / 2
smallSquareView.layer.cornerRadius = smallSquareView.frame.size.width / 2
smallSquareView.clipsToBounds = true
plusSign.layer.cornerRadius = plusSign.frame.size.width / 2
plusSign.clipsToBounds = true
}
Output:
It's a bit tricky, not obvious at first, but not too difficult either.
For the round images, try this:
customView.layer.cornerRadius = customView.bounds.size.width / 2.0
customView.layer.borderWidth = 2.0
customView.layer.borderColor = UIColor.white.cgColor
For the rectangular image with round corners, first line will calculate the .cornerRadius based on height (or you can actually do it for all the cases, and it would also work):
customView.layer.cornerRadius = customView.bounds.size.width / 2.0
Just replace customView with yourCustomViewName and write those 3 lines for each view. That should do the job.
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?
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.
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.
I'm developing an iOS application and using shinobichart for iOS to display data. But I'm stuck with positioning the datapoints outside or inside the bar based on the bar frame.
I'm stuck in positioning the data point labels inside the bar or outside the bar based on bar frame. If bar is big enough to accommodate the data point I need to position the data point inside bar or else outside the bar as in the below image
In - (void)sChart:(ShinobiChart *)chart alterDataPointLabel:(SChartDataPointLabel *)label forDataPoint:(SChartDataPoint *)dataPoint inSeries:(SChartSeries *)series we need to update data points if we wish as per shinobi documentation. But what logic can help to solve such an alignment of data points.
Also I tried to with the following official shinobi example to align data point aside https://www.shinobicontrols.com/blog/customizable-datapoint-labels
But unable to modify for the requirement.
Please help to solve this riddle.
The best way for you to achieve this is to use the alterDataPointLabel method as you have mentioned. I would do something like this:
func sChart(chart: ShinobiChart!, alterDataPointLabel label: SChartDataPointLabel!, forDataPoint dataPoint: SChartDataPoint!, inSeries series: SChartSeries!) {
if Int(label.text!) > [YOUR CUT OFF VALUE]
{
label.frame.origin.y += 15
label.textColor = UIColor.whiteColor()
}
else
{
label.frame.origin.y -= 15
label.textColor = UIColor.blackColor()
}
}
This works best if you know the values your chart is going to be displayed. However as a more generic way of achieving it I would recommend comparing the y value of the data label's origin against y value of the chart canvas. Then for example you could set the it so it appears within the column if it the series was 90% of the canvas?
I'm new to Swift and ios development. I have 6 labels and a horizontal SKScene in my App. I would like to align those 6 labels beautifully and automatically. Now I have fixed the positions and the alignment always looks awful on some screen size while good on other.
I have not used storyboards or other graphical editors for building the ui but everything is done in code. Therefore I'm looking for a programmatic solution (code examples) for handling the alignment.
If you want to place them in the middle of the screen horizontally, but give them different y positions, you could just do something like this for each label:
label.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame) * 0.80)
To place them at different y positions, just multiply by the maxY by a different decimal number. This way, all of the labels are aligned along the x-axis and appear at different y-positions, like a column and they will appear this way on every screen size because they are positioned relative to the screen size and not in a fixed position.
You can align the labels (lets say at the center of the screen) like this.
var label1 = UILabel(CGRectMake: 0, 0, 200, 40)
label1.center = CGPointMake(UIScreen.mainScreen().bounds.size.width/2, 30)
var label2 = UILabel(CGRectMake: 0, 0, 200, 40)
label2.center = CGPointMake(UIScreen.mainScreen().bounds.size.width/2, label1.center.y + 30)
and so on. Just reference the main screen bounds and not static points for alignment, so that they are centered in any screen size.
What I ended up doing was to create an empty SKSprite to which I included the SKLabels. Now I can control by the pixed the distances between labels but align the top-level sprite in the middle of the screen despite screen size.
Before migrating to Awesome 3.5.1 I had two panels at the top of my screen (on top of each other, sort of) and none at the bottom. The code I used to achieve this pre-3.5.* is below:
-- Create the wibox
mywibox[s] = awful.wibox({ position = "top", height = "32", screen = s })
-- Add widgets to the wibox - order matters
mywibox[s].widgets = {
{
{
-- Upper left section
mylauncher,
mytaglist[s],
mypromptbox[s],
-- My custom widgets, separators etc...
layout = awful.widget.layout.horizontal.leftright
},
{
-- Upper right section
mylayoutbox[s],
mytextclock,
-- More widgets, separators, etc...
s == 1 and mysystray or nil,
layout = awful.widget.layout.horizontal.rightleft
},
},
{
-- Lower section (only the tasklist)
mytasklist[s],
},
layout = awful.widget.layout.vertical.flex,
height = mywibox[s].height
}
Now I'm having a hard time trying to figure out how to achieve the same with the 3.5 configuration. At the moment I use pretty basic one panel (with most of the widgets) on top, and one (with the tasklist) at the bottom. The code can be seen below:
-- Create the wibox
mywibox[s] = awful.wibox({ position = "top", height = "18", screen = s })
mywibox2[s] = awful.wibox({ position = "bottom", height = "18", screen = s })
-- Widgets that are aligned to the left
local left_layout = wibox.layout.fixed.horizontal()
left_layout:add(mylauncher)
left_layout:add(mytaglist[s])
left_layout:add(mypromptbox[s])
-- My custom widgets, separators, etc...
-- Widgets that are aligned to the right
local right_layout = wibox.layout.fixed.horizontal()
if s == 1 then right_layout:add(wibox.widget.systray()) end
-- My custom widgets, separators, etc...
right_layout:add(mytextclock)
right_layout:add(mylayoutbox[s])
-- Now bring it all together
local layout = wibox.layout.align.horizontal()
layout:set_left(left_layout)
layout:set_right(right_layout)
local layout2 = wibox.layout.align.horizontal()
layout2:set_middle(mytasklist[s])
mywibox[s]:set_widget(layout)
mywibox2[s]:set_widget(layout2)
If anyone has ideas how to edit my current rc.lua to make it work as the upper code did in Awesome 3.4.*, that'd be greatly appreciated.
You could try something like this, no idea if it does exactly what you want (32 is the height of your wibox according to your code):
local const = wibox.layout.constraint()
const:set_widget(layout)
const:set_strategy("exact")
const:set_height(32/2)
local l = wibox.layout.fixed.vertical()
l:add(const)
l:add(mytasklist[s])
mywibox[s]:set_widget(l)
First it creates a "constraint" layout which makes sure that the layout "layout" (the widgets that should be shown on the top) always get a size of 16px. Then it stacks this constraint layout ontop of the tasklist and displays the result in the wibox.
Some of this code could be shortened a bit in the latest version, but I am not sure if 3.5.1 has those convenience arguments already.
I've done similar with following code:
wiboxes["top"]=awful.wibox({position="top",height=26})
local top_layout = wibox.layout.fixed.horizontal()
sublayout["cpu"] = wibox.layout.fixed.horizontal()
for i=2,3 do
sublayout["cpu" .. i] = wibox.layout.fixed.horizontal()
sublayout["cpu" .. i]:add(graphs["cpu"]..i) -- the graphs table already initialized
sublayout["cpu" .. i]:add(textboxes["cpu"]..i) -- textboxes table already initialized
sublayout["cpu"]:add(sublayout["cpu"..i)
end
.....
top_layout:add(sublayout["cpu"])
.....
wiboxes["top"]:set_widget(top_layout)
With this code I've two graphs and textboxes to see the CPUs usage (every core), first is on top, second is down. It should work with taglist or any other widget.