For reproducing the problem, I have added 2 controls to a content page: Picker and Entry. The container is a TableView section.
If I click on the Entry control, causing the keyboard to open, or enter characters in it, the Picker selection is opening. It's opening every time I enter a character or removing one (so when the value is changing).
I don't have this problem if the main container isn't a TableView, but for example a StackLayout.
I have this problem since Xamarin Forms v3.3. In previous versions, like 3.2, this problem didn't exist. The problem also exists in the 3.4 beta.
Also: the problem only occurs in Android (version 4 - 9). Not in iOS.
Below you'll find my code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PickerBugXF33"
x:Class="PickerBugXF33.MainPage">
<StackLayout>
<TableView x:Name="testTableView" Intent="Form" HasUnevenRows="true" />
</StackLayout>
</ContentPage>
Code behind:
using Xamarin.Forms;
namespace PickerBugXF33
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
testTableView.Root = new TableRoot();
var section = new TableSection("Test section");
testTableView.Root.Add(section);
var viewCell = new ViewCell();
section.Add(viewCell);
var stack = new StackLayout() { Orientation = StackOrientation.Vertical };
viewCell.View = stack;
var picker = new Picker();
picker.Items.Add("Test item in picker");
stack.Children.Add(picker);
var entry = new Entry();
stack.Children.Add(entry);
}
}
}
NB: This is a test project. The real live project is much larger in which the page has to be created via code.
Update 1, 11/9/2018: Might be solved by commit: https://github.com/xamarin/Xamarin.Forms/pull/4344/commits/8401d81745ad248b5b70aa669863c8b8c8753e66
Related
Here is the code I have:
<?xml version="1.0" encoding="UTF-8" ?>
<pages:PopupPage
x:Class="Memorise.DecksTab.CopyDeckPopup"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup">
<Label />
<Label />
</pages:PopupPage>
With backing code:
csharp
[ContentProperty("Contents")]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CopyDeckPopup : Rg.Plugins.Popup.Pages.PopupPage
{
StackLayout contentStack { get; } = new StackLayout()
{
Spacing = 0,
Padding = new Thickness(0),
Orientation = StackOrientation.Vertical
};
public IList<View> Contents { get => contentStack.Children; }
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
Content = contentStack;
}
In the first XAML I am getting an error on the 2nd Label saying
The property "Content" is set more than once
I can reproduce the behavior.
Nevertheless, on my side even though VS displays that warning/error if i run the project it deploys correctly and both labels are displayed.
It seems that VS does not recognize that the ContentProperty is being overriden, and supposes instead that you are trying to add both Labels to Content, which is wrong since you are adding them to your custom ContentProperty Contents!
Please run the project and let me know if the deploy fails...
UPDATE
The whole issue looks to me like a limitation of VS. At the end it is just a warning, and you should be able to ignore it without any danger.
If on the other hand you opt to set the labels on code you could write
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
Content = contentStack;
Contents.Add(new Label() { Text = "ABC" });
Contents.Add(new Label() { Text = "DEF" });
}
But now this looks redundant since as i understand ContentProperty's is an attribute that the
XAML processor uses to determine the content property.
Decorating types with ContentPropertyAttribute allows shorter XAML syntax.
If you code everything on C# just use the good old Stacklayout and write your code like
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CopyDeckPopup : Rg.Plugins.Popup.Pages.PopupPage
{
public CopyDeckPopup(string clickedDeckName, string clickedDeckDescription)
{
BindingContext = new CopyDeckPopupViewModel(clickedDeckName, clickedDeckDescription);
InitializeComponent();
StackLayout contentStack = new StackLayout()
{
Spacing = 0,
Padding = new Thickness(0),
Orientation = StackOrientation.Vertical,
Children =
{
new Label() { Text = "ABC" },
new Label() { Text = "ABC" }
}
};
Content = contentStack;
}
I am coding a social networking app using Xamarin in Visual Studio, its a portable project with an Android and iOS project.
When the MainPage class is navigated to it opens a URL and reads the page and saves it as a string. I need it to split at every "". I'm thinking I should use a for loop but I don't know what to do next. I would like each chunk to have its own layout box, I have yet to learn which layout to use and what each one is best for. In each box, it would have a label (content) and possibly an image (if the post comes with one, it would be a URL so it would open the URL and display that image)
Basically for each one I want to be able to edit the following
for(string chunk : data.split("<br/">){
<Layout?>
<label Text="*Content from the current chunk*"/>
if(*contains image*){
<image>*Open url and display the image*</image>
}
</Layout?>
}
This is also all inside of a scrollview so they all scroll together...
Parsing of chunk strings not shown.
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:StackOverflow1"
x:Class="StackOverflow1.MainPage"
Appearing="ContentPage_Appearing">
<ScrollView>
<StackLayout x:Name="mainStackLayout" />
</ScrollView>
</ContentPage>
MainPage.xaml.cs:
// ...
public partial class MainPage : ContentPage
{
private List<Chunk> chunks = new List<Chunk>();
// ...
private void ContentPage_Appearing(object sender, EventArgs e)
{
StackLayout childLayout;
foreach (Chunk chunk in chunks)
{
childLayout = new StackLayout();
Image image = new Image() { Source = chunk.url, HorizontalOptions = LayoutOptions.Start };
Label label = new Label() { Text = chunk.text, HorizontalOptions = LayoutOptions.Start };
childLayout.Children.Add(image);
childLayout.Children.Add(label);
mainStackLayout.Children.Add(childLayout);
}
}
}
// ...
I want to open an Android activity for Android devices and iOS screen for iOS devices from login screen. The code of the login screen, I have written is in shared portable code Area. I have used interface and #if ANDROID #endif, but it is also not working.
Android screen will only contain a textview and an iOS screen will contain a Image. This is my Login Page in portable folder
namespace DemoApp
{
public class HomePage : ContentPage
{
public HomePage()
{
var title = new Label
{
Text = "Welcome to CloudCakes",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
var email = new Entry
{
Placeholder = "E-Mail",
};
var password = new Entry
{
Placeholder = "Password",
IsPassword = true
};
var login = new Button
{
Text = "Login"
};
// With the `PushModalAsync` method we navigate the user
// the the orders page and do not give them an option to
// navigate back to the Homepage by clicking the back button
login.Clicked += (sender, e) =>
{
App.UserPreferences.Open();
// await Navigation.PushModalAsync(new MainPage());
};
Content = new StackLayout
{
Padding = 30,
Spacing = 10,
Children = { title, email, password, login}
};
}
}
}
And, this is the page in Droid folder where I want to navigate on clicking login button
name space
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page1 : IUserPreferences
{
public Page1()
{
InitializeComponent();
}
public void Open()
{
var title = new Label
{
Text = "Welcome to Xamarin Forms IOS Screen!!",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
Content = new StackLayout
{
Padding = 30,
Spacing = 10,
Children = { title }
};
}
}
}
Open is a method of interface which is present in the portable folder.
I assume that you're using Xamarin.Forms, so what you need to do is actually quite easy to achieve.
Instead of having a separate page for each platform, create one new XAML page with the following code:
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourApp.Views.MainPage">
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<Image Source="something.png" />
</OnPlatform.iOS>
<OnPlatform.Android>
<Label Text="Android" />
</OnPlatform.Android>
</OnPlatform>
</ContentView>
</ContentPage>
This way you can control what to have on the page for each platform.
To navigate to MainPage from your LoginPage, you need to implement the Clicked event (or preferrably use Commands) in the code behind (MainPage.xaml.cs) and do the navigation there:
private void SomeButton_Clicked(object sender, System.EventArgs e)
{
await this.Navigation.PushAsync(new MainPage());
}
In the long run, you should look into doing all this outside the code behind with ViewModel's and Commands.
Edit: Since the first solution didn't work for you, here's what to do:
1) Subclass ContentPage in your core project.
public class MainPage : ContentPage { }
2) Implement a PageRenderer for each platform separately. You'll be able to use native layout definition for your pages as you mentioned.
There's a great article on the Xamarin blog on how to achieve this. You can also find the source code on GitHub.
In my Xamarin.Forms Prism app, I have a MasterDetailPage to handle navigation. The MasterBehavior is set to Popover.
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:My.Mobile.Application.Views;assembly=My.Mobile.Application"
x:Class="My.Mobile.Application.Frame.MainPage"
MasterBehavior="Popover">
<MasterDetailPage.Master>
<views:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
</MasterDetailPage>
When the master is visible, if I select the menu item that is already being displayed as the detail item, the master does not automatically dismiss; I have to swipe the master closed if I want to stay on the same page.
I tried manually registering to the ItemSelected event on my master's list view to be able to explicitly set IsPresented = false on the MasterDetailPage, but the event does not fire when selecting the item that is already being displayed:
public partial class MainPage : MasterDetailPage
{
public MainPage()
{
InitializeComponent();
masterPage.ListView.ItemSelected += OnItemSelected;
}
private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
IsPresented = false;
}
}
This differs from the behavior of the Xamarin.Forms sample Master-Detail app, which closes the master when a selection is made (even if it is the same item that is already being displayed).
Is this something that is being controlled by Prism?
Is there any chance that I can remove the title bar of the app in Xamarin.Forms? I am working on a Xamarin.Forms Portable project. I tried a lot of solutions, but neither worked, I couldn't even start the app.
First attempt I tried adding this to my AndroidManifest.xml, didn't work:
android:theme="#android:style/Theme.NoTitleBar"
Second attempt I tried creating a styles.xml in Resources/values, which was:
<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.Default" parent="#android:style/Theme"></style>
<style name="Theme.NoTitle" parent="#android:style/Theme.NoTitleBar"></style>
<style name="Theme.FullScreen" parent="#android:style/Theme.NoTitleBar.Fullscreen"></style>
</resources>
And then I added this to my AndroidManifest.xml (didn't work either)
android:theme="#style/Theme.NoTitle"
Third attempt I tried adding this to my OnCreate method in MainActivity.cs (didn't work).
RequestWindowFeature(WindowFeatures.NoTitle);
Can anyone help me with this?
If you want to remove the title bar on the initial page, the quickest and easiest way to do it is to go to to the contentpage heading in your XAML for the page and type
NavigationPage.HasNavigationBar="False"
so the XAML would like something like this
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="YourClass.YourPage"
NavigationPage.HasNavigationBar="False">
This can be done in PCL:
var page = new LoginPage();
NavigationPage.SetHasNavigationBar(page, false); // call this method every time before you push a page (no title bar)
await navigation.PushAsync(page);
If you are using old FormsApplicationActivity,
try, add this in OnCreate(Bundle bundle) method
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle)
Forms.SetTitleBarVisibility(AndroidTitleBarVisibility.Never);
Forms.Init(this, bundle);
}
This one seems do the app wide setting, but I am not so sure, as I don't use FormsApplicationActivity anymore.
Using the latest version of Xamarin.Forms I found that if you use:
await Navigation.PushAsync(new NextPage())
//Title on NextPage is displayed
await Navigation.PushModalAsync(new NextPage())
//Title on NextPage is not displayed
Nathan
i had this problem before and my solution was adding this line of code to the MainPage.xaml NavigationPage.HasNavigationBar="False"
<?xml version="1.0" encoding="utf-8" ?>
<xf:BottomBarPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xf="clr-namespace:BottomBar.XamarinForms;assembly=BottomBar.XamarinForms"
xmlns:local="clr-namespace:App;assembly=App"
NavigationPage.HasNavigationBar="False" <-- This line !-->
x:Class="App.MainPage">
and it worked for me !
Theme = "#android:style/Theme.NoTitleBar"
.
using Android.App;
using Android.OS;
using Android.Webkit;
using Android.Views; // Webkit required for WebView
namespace LoadWebPage {
[Activity(Label = "LoadWebPage", MainLauncher = true, Icon = "#drawable/icon", Theme = "#android:style/Theme.NoTitleBar")]
public class Activity1 : Activity {
protected override void OnCreate (Bundle bundle)
For iOS this single line (e.g. in the constructor of the page) works just fine.
NavigationPage.SetHasNavigationBar(page, false);
But Android is ignoring it, also when put in the XAML of the page.
As mentioned above by Bonelol this method has to be called each time before you push a page.
I use Prism, so I can't access the creation and push of a page.
So I just created a custom renderer for NavigationPage and put this line there. Maybe this will help someone else.
[assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationRenderer))]
namespace MyApp.Droid.Renderer
{
public class CustomNavigationRenderer : NavigationPageRenderer
{
public CustomNavigationRenderer(Context context) : base(context)
{
}
protected override Task<bool> OnPushAsync(Page view, bool animated)
{
NavigationPage.SetHasNavigationBar(view, false);
return base.OnPushAsync(view, animated);
}
}
}
Try This:
private ActionBar ab;
protected override void OnCreate(Bundle savedInstanceState)
{
try
{
base.OnCreate(savedInstanceState);
ab = this.ActionBar;
ab.Hide();
}
catch (Exception ex)
{
}
}
Try this one, just found it in one of view xaml in flyout tab
Shell.NavBarIsVisible="False"
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="YourClass.Views.YourPage" Shell.NavBarIsVisible="False">