Hide/Remove a child view in Xamarin Studio - c#

I added a UITabBarController to a view via the AddChildViewController method. I then navigate onto the next view and my tab bar appears, hey presto. As I'm in a new view now though, how can I remove the UITabBarController for the child view, as when I use the RemoveFromSuperview function it only removes the parent view and the bar still appears if I push another view.
View where child view is added:
tabController = new UITabBarController ();
tabController.ViewControllers = new UIViewController[] {
vc1,
vc2,
vc3
};
tabController.ViewControllers [0].TabBarItem.Title = "vc1";
tabController.ViewControllers [1].TabBarItem.Title = "vc2";
tabController.ViewControllers [2].TabBarItem.Title = "vc3";
this.NavigationController.AddChildViewController(tabController);
this.NavigationController.Add(tabController.View);
Much Appreciated!
EDIT - A bit more detail on my problem here: http://forums.xamarin.com/discussion/6473/hide-tabbarcontroller-when-added-as-a-child-view#latest

If I understand correctly, you want your initial ViewController to be a TabViewController and when a user selects something in one of the ViewControllers it transitions to a ViewController without the TabView buttons at the bottom.
If so, here's what you need to do.
In AppDelegate.cs you need to setup the window/view controllers like so:
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
rootController = new UINavigationController ();
window.RootViewController = rootController;
var tabController = new UITabBarController ();
var vc1 = new TestController1();
var vc2 = new TestController2();
var vc3 = new TestController3();
tabController.ViewControllers = new UIViewController[] {
vc1,
vc2,
vc3
};
tabController.ViewControllers [0].TabBarItem.Title = "vc1";
tabController.ViewControllers [1].TabBarItem.Title = "vc2";
tabController.ViewControllers [2].TabBarItem.Title = "vc3";
this.rootController.PushViewController(tabController, false);
window.MakeKeyAndVisible ();
return true;
}
Once you have this setup, you can transition to a new view like so from within the class for TestController1:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var button = UIButton.FromType(UIButtonType.RoundedRect);
button.Frame = new RectangleF (10, 10, 200, 30);
button.SetTitle ("Go Child Controller", UIControlState.Normal);
button.TouchUpInside += (object sender, EventArgs e) => {
NavigationController.PushViewController(new TestController4(), true);
};
View.AddSubview (button);
}
Also, you can simplify setting the tab button titles.
Instead of doing this:
tabController.ViewControllers [0].TabBarItem.Title = "vc1";
You can just set the title from within your child UIViewController:
public class TestController1:UIViewController
{
public TestController1 ()
{
this.Title = "vc1";
}
...

Related

UWP Tab View not responding

I have a page with a Tab View. Inside every tab is another page. Whenever I try to interact with the tab, nothing works. I tried interacting with it with SettingsPage as the content, and it worked.
MainPage - contains the tabs
TabbedMainPage - contains the workspace
SettigsPage - contains settings
MainPage:
private void TabView_AddTabButtonClick(TabView sender, object args)
{
sender.TabItems.Add(CreateNewTab());
}
public TabViewItem OpenSettingsTab()
{
TabViewItem newItem = new TabViewItem();
newItem.Header = "Settings";
newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Setting };
Frame frame = new Frame();
frame.Navigate(typeof(SettingsPage));
newItem.Content = frame;
TabbedView.UpdateLayout();
return newItem;
}
public void CreateSettingsTab()
{
TabbedView.TabItems.Add(OpenSettingsTab());
TabbedView.UpdateLayout();
TabbedView.SelectedIndex = TabbedView.TabItems.Count - 1;
}
public TabViewItem CreateNewTab()
{
TabViewItem newItem = new TabViewItem();
newItem.Header = "New Tab";
newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Document };
Frame frame = new Frame();
frame.Navigate(typeof(TabbedMainPage));
newItem.Content = frame;
TabbedView.UpdateLayout();
return newItem;
}
private void TabbedView_Loaded(object sender, RoutedEventArgs e)
{
var S = sender as TabView;
if (S.TabItems.Count == 0)
{
S.TabItems.Add(CreateNewTab());
}
TabbedView.UpdateLayout();
}
TabbedMainPage has the following components: ColorPicker, DropDownButton, MenuBar, Border, Button, CheckBox, ComboBox, Flyout, Grid, Image, MenuFlyout, Pivot, PivotItem, StackPanel, TextBlock, TextBox, Flyout, Popup, RichEditBox, ScrollViewer, Slider, ToggleButton and Tooltip.
I think it might be caused by overloading with components, but I'm not sure. I also have these in my code:
MediaElement ME;
SpeechSynthesizer Synth;
public StorageFile TXTFile;
public IRandomAccessStream RAS;
private readonly PrintHelperOptions PP = new PrintHelperOptions();
var LS = ApplicationData.Current.LocalSettings;
var TB = ApplicationView.GetForCurrentView().TitleBar;
var CTB = CoreApplication.GetCurrentView().TitleBar;
I managed to fix the bug by removing the Pivot from the toolbar. It was interfering with the tab functionality, so I merged all the items together.

Xamarin menu with ToolbarItem icon

I want to do something like this example, but i can't.
I try a lot of plugins and I cant find the way to implement.
Someone know or can tell me how can I do?
I want to show a display popup menu when click in one ToolbarItem on a MasterDetailPage.
My actual app:
What i want:
I think you can take a look to SlideOverKit
public SlideDownMenuView ()
{
InitializeComponent ();
// You must set HeightRequest in this case
this.HeightRequest = 600;
// You must set IsFullScreen in this case,
// otherwise you need to set WidthRequest,
// just like the QuickInnerMenu sample
this.IsFullScreen = true;
this.MenuOrientations = MenuOrientation.TopToBottom;
// You must set BackgroundColor,
// and you cannot put another layout with background color cover the whole View
// otherwise, it cannot be dragged on Android
this.BackgroundColor = Color.FromHex ("#D8DDE7");
}
Otherwise with enter link description here
you can try with this code...
public partial class App : Application
{
public App()
{
InitializeComponent();
MasterDetailPage mdpage = new MasterDetailPage();
mdpage.Master = new ContentPage() { Title = "Master", BackgroundColor = Color.Red };
ToolbarItem tbi = new ToolbarItem() { Text = "POPUP" };
tbi.Clicked += async (object sender, System.EventArgs e) => {
StackLayout sl = new StackLayout() { HorizontalOptions = LayoutOptions.End, VerticalOptions = LayoutOptions.Start, BackgroundColor = Color.Pink, WidthRequest = 100, HeightRequest = 200 };
Rg.Plugins.Popup.Pages.PopupPage mypopup = new Rg.Plugins.Popup.Pages.PopupPage() {BackgroundColor = Color.Transparent };
mypopup.Content = sl;
await MainPage.Navigation.PushPopupAsync(mypopup);
};
ContentPage detail = new ContentPage() { Title = "Detail", BackgroundColor = Color.Green, };
detail.ToolbarItems.Add(tbi);
mdpage.Detail = new NavigationPage(detail);
MainPage = mdpage;
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}

How to handle the Tap of a ViewCell defined in code in Xamarin.Forms?

I have a multiple ViewCell and ImageCell subclasses inside a TableView.
I would like to execute some code when the user taps the cell. The whole cell highlights whenever it's touched, but I don't see any event handler to use here.
Isn't there a XAML Tapped equivalent for this but in code only?
private void SetTableView()
{
Content = new TableView
{
HasUnevenRows = true,
Intent = TableIntent.Menu,
Root = new TableRoot()
{
new TableSection()
{
new ProfileCell(ImageSource.FromFile("profile_placeholder.png"), "Casa de Férias")
},
new TableSection()
{
new InfoCell()
{
Type = InfoCellTypes.Pending,
Text = "Avaliação do Imóvel",
Detail = "Estado do Processo"
}
}
}
};
}
I'm sure there must be some API that handles this. Maybe I'm just not looking in the right place?
Thank you!
This can be accomplished by adding a TapGestureRecognizer to the cell's view layout.
var absoluteLayout = new AbsoluteLayout
{
Children =
{
photo,
editImage,
label
}
};
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.NumberOfTapsRequired = 1;
tapGestureRecognizer.Tapped += (s, e) => {
// handle the tap
};
absoluteLayout.GestureRecognizers.Add(tapGestureRecognizer);
View = absoluteLayout;
EDIT:
Or, a better alternative, using the Tapped property of the ViewCell, so it doesn't break the "Tap Animation":
Tapped += new EventHandler((e, s) => {
if (command.CanExecute(null))
{
command.Execute(null);
}
});

Xamarin.Forms: Change RelativeLayout constraints afterwards

Is it possible to change the constraints of a RelativeLayout after they have been set one time?
In the documentation I see methods like GetBoundsConstraint(BindableObject), but I think you can only use them if you have a XAML file. For now I'm trying to do this in code. I get null if I try
RelativeLayout.GetBoundsConstraint(this.label);
The only way I found out is to remove the children from the layout and add it with the new constraints again.
Example:
public class TestPage : ContentPage
{
private RelativeLayout relativeLayout;
private BoxView view;
private bool moreWidth = false;
public TestPage()
{
this.view = new BoxView
{
BackgroundColor = Color.Yellow,
};
Button button = new Button
{
Text = "change",
TextColor = Color.Black,
};
button.Clicked += Button_Clicked;
this.relativeLayout = new RelativeLayout();
this.relativeLayout.Children.Add(this.view,
Constraint.Constant(0),
Constraint.Constant(0),
Constraint.Constant(80),
Constraint.RelativeToParent((parent) =>
{
return parent.Height;
}));
this.relativeLayout.Children.Add(button,
Constraint.RelativeToParent((parent) =>
{
return parent.Width / 2;
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height / 2;
}));
this.Content = this.relativeLayout;
}
private void Button_Clicked(object sender, EventArgs e)
{
double width = 0;
if(this.moreWidth)
{
width = 120;
}
else
{
width = 80;
}
var c= BoundsConstraint.FromExpression((Expression<Func<Rectangle>>)(() => new Rectangle(0, 0, width, this.Content.Height)), new View[0]);
RelativeLayout.SetBoundsConstraint(this.view, c);
this.relativeLayout.ForceLayout();
this.moreWidth = !this.moreWidth;
}
}
It does not officially possible with the current version of Xamarin Forms. The RelativeLayout container only recomputes constraints when adding/removing items from its children collection (it caches the solved constraints - presumable for performance). Even though the various constraints are implemented as Bindable Properties, they still do not get recomputed when changed.
I assume that the intention is to someday respect constraint updates, which would be useful with animations for example, but for now it doesn't appear to work that way.
HOWEVER, I took a look at the decompiled source for RelativeLayout and it is possible to hack together a way around it - but it might not suit your needs, depending on how much functionality you require and how complex your constraint definitions are.
See this example code (the key part is setting the constraint using SetBoundsConstraint, which overrides the internally computed bounds of the added view - and then calling ForceLayout()):
public partial class App : Application
{
public App ()
{
var label = new Label {
Text = "Test",
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
BackgroundColor = Color.Silver
};
var layout = new RelativeLayout ();
layout.Children.Add (label,
Constraint.Constant (50),
Constraint.Constant (100),
Constraint.Constant (260),
Constraint.Constant (30));
MainPage = new ContentPage {
Content = layout
};
var fwd = true;
layout.Animate ("bounce",
(delta) => {
var d = fwd ? delta : 1.0 - delta;
var y = 100.0 + (50.0 * d);
var c = BoundsConstraint.FromExpression ((Expression<Func<Rectangle>>)(() => new Rectangle (50, y, 260, 30)), new View [0]);
RelativeLayout.SetBoundsConstraint(label, c);
layout.ForceLayout ();
}, 16, 800, Easing.SinInOut, (f, b) => {
// reset direction
fwd = !fwd;
}, () => {
// keep bouncing
return true;
});
}
}
Yes. This possible.
Layout code:
<StackLayout RelativeLayout.XConstraint="{Binding XConstaint}" ...>
VM code:
public Constraint XConstaint
{
get => _xConstaint;
set { SetFieldValue(ref _xConstaint, value, nameof(XConstaint)); }
}
public override void OnAppearing()
{
base.OnAppearing();
XConstaint = Constraint.RelativeToParent((parent) => { return parent.Width - 128; });
}
If i understood you correctly , I would try the following
Implement SizeChanged event for relativeLayout
like :-
var relativeLayout = new RelativeLayout ();
relativeLayout.SizeChanged += someEventForTesting;
and invoke the event whenever you want to resize the relative layout or some particular child.
public void someEventForTesting(Object sender , EventArgs)
{
var layout = (RelativeLayout)sender ;
//here you have access to layout and every child , you can add them again with new constraint .
}

Storyboard animation

I made a small WPF application to slide UserControls in and out, the problem I have is when a UserControl animated to slide in, then I click the button to slide another UserControl in, they both slide out - I'm not sure why this is?
public UserControl1()
{
InitializeComponent();
}
public void SlideIn(UserControl uc)
{
ThicknessAnimation tAnimation = new ThicknessAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
tAnimation.From = new Thickness(500, 0, -500, 0);
tAnimation.To = new Thickness(0);
tAnimation.DecelerationRatio = 0.9;
Storyboard.SetTargetName(tAnimation, uc.Name);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(MarginProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin(uc);
this.Content = uc;
}
public void SlideOut(UserControl uc)
{
ThicknessAnimation tAnimation = new ThicknessAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
tAnimation.To = new Thickness(-500, 0, 500, 0);
tAnimation.DecelerationRatio = 0.9;
Storyboard.SetTargetName(tAnimation, uc.Name);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(MarginProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin(this);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
SlideOut(userControl1);
UserControl2 uc2 = new UserControl2();
SlideIn(uc2);
}
Do you set the Name property of the UserControl somewhere? Or to be more precise, do you give the second UserControl a different Name than the first one? Your animations get their target set by
Storyboard.SetTargetName(tAnimation, uc.Name);
so names should be different. Alternatively you may call
Storyboard.SetTarget(tAnimation, uc);
to specify the target.

Categories