Dear fellow programmers.
Currently my strings are loaded, and 5 buttons are created with these titles from the database.
Yet the buttons are not visible on the iOS app.
What am I missing.
I am using Xamarin.iOS and c#
Thanks in advance
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using System.Drawing;
using Ola.ServiceClients;
using System.Threading.Tasks;
using PortableRest;
using Ola.Shared.Models;
using System.Net.Http;
using System.Net.Http.Headers;
namespace Ola.iOS
{
partial class NavigationViewController : UIViewController
{
//private MenuItem[] menuItems;
private MenuItem[] drawerItems;
public string token = "";
public NavigationViewController(IntPtr handle)
: base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
LoadMenu();
}
public async void LoadMenu()
{
RestResponse<MenuItem[]> response = await NavigationClient.Current.GetMenu(token);
//HttpResponseHeaders responseHeaders = response.HttpResponseMessage.Headers;
//HttpRequestMessage requestMessage = response.HttpResponseMessage.RequestMessage;
if (response != null && response.Content != null && response.Content.Length > 0)
{
//menuItems = response.Content;
for (int i = 0; i < response.Content.Length; i++)
{
UIButton button = UIButton.FromType(UIButtonType.RoundedRect);
button.SetTitle(response.Content[i].Text, UIControlState.Normal);
this.Add(button);
System.Console.WriteLine("Button created");
}
System.Console.WriteLine();
}
}
}
}
Greetings
Dave
Add the following code to show your buttons:
this.View.AddSubview(button);
instead of:
this.Add(button);
Make sure you are setting button.Frame property, adding button to parent View and also you should try to set background color as by default its transparent.EditI'm not sure if that will make any difference but try to create buttons differently e.i var button = new UIButton(new RectangleF());And one more thing I'm thinking of may be transparency, make sure that parent View and buttons do not have alpha set to 0Edit 2One more thing ! Try wrap call where you adding buttons to view by calling it in InvokeOnMainThread(() =>
{
this.View.AddSubview(button);
});
method !
Related
I'm wanting to remove the burger menu icon whilst retaining the navigation bar. I want to add content to the NavigationPage.TitleView property and i would like it to take the full width of the page. In the image i've attached, the yellow background colour shows the width that the TitleView is currently occupying.
I know in forms you can control the visibility of the back button, is there a way you can also control the burger menu icon? Based on what i've been reading, this will most likely require a custom renderer, which i've tried with no luck. I need to support iOS & Android.
In the android, you can use following custom renderer code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.Graphics.Drawable;
using Android.Views;
using Android.Widget;
using MesterDetailspage.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MyMasterDetailRenderer))]
namespace MesterDetailspage.Droid
{
public class MyMasterDetailRenderer : MasterDetailPageRenderer
{
public MyMasterDetailRenderer(Context context) : base(context)
{
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
for (var i = 0; i < toolbar.ChildCount; i++)
{
var imageButton = toolbar.GetChildAt(i) as Android.Widget.ImageButton;
var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
if (drawerArrow == null)
continue;
bool displayBack = false;
var app = Xamarin.Forms.Application.Current;
var detailPage = (app.MainPage as MasterDetailPage).Detail;
var navPageLevel = detailPage.Navigation.NavigationStack.Count;
if (navPageLevel > 1)
displayBack = true;
if (!displayBack)
ChangeIcon(imageButton, Resource.Drawable.test1);
if (displayBack) ;
//ChangeIcon(imageButton, Resource.Drawable.back1);
}
}
}
private void ChangeIcon(Android.Widget.ImageButton imageButton, int id)
{
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
imageButton.SetImageDrawable(Context.GetDrawable(id));
imageButton.SetImageResource(id);
}
}
}
I set a transparent background image.
Here is running screenshot.
For iOS, just set the IconImageSource="test1.png" in MasterDetailPage tag in xamarin forms xaml.
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
IconImageSource="test1.png"
xmlns:views="clr-namespace:MesterDetailspage.Views"
x:Class="MesterDetailspage.Views.MainPage">
As it turns out, at the moment, this is not possible. You can hide the burger menu but it still takes up space (see Leon Lu's answer).
My solution was to create a custom navigation bar, that way i have full control. If you want to do this first remove the navigation bar:
NavigationPage.SetHasNavigationBar(this, false);
Then add your custom nav using regular xaml code, just like you would with any other component.
One to thing to keep in mind is that in ios your nav can show where the notch is, to fix this you need to use this code:
On<iOS>().SetUseSafeArea(true);
So when I designed the navigation bar for my Android application I made it look like this:
The only problem I have with coding this is that when I add the .png images for each icon into my XAML code on the MainPage.xaml the icons end up looking like this (the icons just turn to into black shapes with no other colours).
Is android only capable of handling single colour icons for Android?
Is there any way to disable this default feature?
I know that the android style guidelines specify that you shouldn't use more than one colour for the icon in your navigation bar but I need to make an exception for this app.
If you want to use the colorful icon in the Tabbedpage, you should create a custom renderer for Tabbedpage
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
using TabbedDemo.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(MyTabbedRenderer))]
namespace TabbedDemo.Droid
{
public class MyTabbedRenderer : TabbedPageRenderer
{
public MyTabbedRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
if (e.OldElement == null && e.NewElement != null)
{
for (int i = 0; i <= this.ViewGroup.ChildCount - 1; i++)
{
var childView = this.ViewGroup.GetChildAt(i);
if (childView is ViewGroup viewGroup)
{
for (int j = 0; j <= viewGroup.ChildCount - 1; j++)
{
var childRelativeLayoutView = viewGroup.GetChildAt(j);
if (childRelativeLayoutView is BottomNavigationView)
{
((BottomNavigationView)childRelativeLayoutView).ItemIconTintList = null;
}
}
}
}
}
}
}
}
Here is running screenshot.
In my app I have a list activity and in it you can check multiple items in the list, how can I have the checked items checked the next time the listactivity is opened? I think the way to do it is through using getview but I dont know how to implement that in my class because I am not using a custom listadapter, if someone could show me how that would be great
Below is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System.Linq;
namespace BoostITAndroid
{
[Activity(Label = "My Activity")]
public class Selector : ListActivity
{
int[] numlist = new int[45];
String[] Options;
int[] OptionsID;
String item;
int counter = 0;
Button save, cancel;
int vehicleId;
int category;
private List<AvailableFeatures> list;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
List<Makes> listmakes = VehicleAssetsDB.GetMakes();
Options = new String[listmakes.Count];
OptionsID = new int[listmakes.Count];
Options = listmakes.Select(Makes => Makes.Make).ToArray();
OptionsID = listmakes.Select(Makes => Makes.ID).ToArray();
ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItem1, Options);
}
}
}
Below is my onclicklistener
protected override void OnListItemClick(ListView l, View v, int position, long id)
{
l.ChoiceMode = ChoiceMode.Multiple;
Android.Util.SparseBooleanArray checkedItems = l.CheckedItemPositions;
if (!checkedItems.Get(position))
{
l.SetItemChecked(position, false);
}
if (checkedItems.Get(position))
{
l.SetItemChecked(position, true);
}
}
if you want your checkboxes to retain their state, you have to save that somewhere in persistent storage. Depending on the purpose of the checkbox, you could store the state in SharedPreferences, or you could create a SQLite DB and store the values there.
Either way, you will likely need a custom Adapter to display your list and set the checkbox states depending on the saved state of each.
See here for details = http://developer.android.com/guide/topics/data/data-storage.html
Hope that helps.
Old Title: Prevent dynamically created control from retaining value
Old Info:
The reason I need to do this is because I am trying to create a work around for a required field validator for an Image control. The way my code works is I have a Image control beside a Button, a user clicks on the button and then is prompted to upload an image. I need to ensure that an image is uploaded before the user can move onto the next stage.
Since there is no required field validator for an image control, I created a textbox which is suppose to display the imageURL of the image control every time the image control is recreated on postbacks. However, the textbox always retains the value from the initial creation of the control.
* Note: all controls on the page are dynamically created.
The first thing I do is create the image control and add it to an HTML Table. This works fine. Right after that I find the table cell and add the textbox to the cell that has an image control:
HtmlTableCell tc = (HtmlTableCell)customProperties.FindControl("tcControl_" + (i + 1).ToString());
RadBinaryImage rbi = (RadBinaryImage)customProperties.FindControl("CustomControl" + (i + 1).ToString());
TextBox photoValue = new TextBox();
photoValue.ID = "CustomControl" + (i + 1).ToString() + "_txt";
photoValue.Text = rbi.imageUrl;
This occurs everytime I create all the controls. For all the controls they all retain their values, this is the only control which I don't want this to happen. Does anyone know of how this can be done? Or another way of validating an image control?
Thanks for your time,
All comments/answers are appreciated (:
SOLVED:
I created a modified version of a checkboxlist required field validator that I found here.
Here is the code: I replaced the namespace with ######## for security reasons.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Web.UI;
namespace #######################################
{
public class RequiredFieldValidatorForImages :
System.Web.UI.WebControls.BaseValidator
{
private Control _ctrl;
public RequiredFieldValidatorForImages()
{
base.EnableClientScript = false;
}
protected override bool ControlPropertiesValid()
{
Control ctrl = FindControl(ControlToValidate);
if (ctrl != null)
{
_ctrl = (Control)ctrl;
return (_ctrl != null);
}
else
return false; // raise exception
}
protected override bool EvaluateIsValid()
{
try
{
Image rbi = (Image)_ctrl;
return rbi.ImageUrl != "~/images/noimages.jpg";
}
catch
{
RadBinaryImage rbi = (RadBinaryImage)_ctrl;
return rbi.ImageUrl != "~/images/noimages.jpg";
}
}
}
}
Solved:
I created a modified version of a checkboxlist required field validator that I found here.
Here is the code: I replaced the namespace with ######## for security reasons.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Web.UI;
namespace #######################################
{
public class RequiredFieldValidatorForImages :
System.Web.UI.WebControls.BaseValidator
{
private Control _ctrl;
public RequiredFieldValidatorForImages()
{
base.EnableClientScript = false;
}
protected override bool ControlPropertiesValid()
{
Control ctrl = FindControl(ControlToValidate);
if (ctrl != null)
{
_ctrl = (Control)ctrl;
return (_ctrl != null);
}
else
return false; // raise exception
}
protected override bool EvaluateIsValid()
{
try
{
Image rbi = (Image)_ctrl;
return rbi.ImageUrl != "~/images/noimages.jpg";
}
catch
{
RadBinaryImage rbi = (RadBinaryImage)_ctrl;
return rbi.ImageUrl != "~/images/noimages.jpg";
}
}
}
}
I try to create a GridPanel programmatically using a LinqDataSource as shown in the examples.
So far I can see my empty GridPanel without any data inside cause my GridPanel is missing the ColumnModel used to show the data.
As I can't find the right method to add the ColumnModel to the GridPanel I need to ask you.
My Code which is used to create my GridPanel and everything is underneath.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace IntraNET_Prototype
{
public partial class MitarbeiterUndTelefonliste : System.Web.UI.Page
{
public LinqDataSource MitarbeiterDataSource = new LinqDataSource();
public Ext.Net.GridPanel MitarbeiterGridPanel = new Ext.Net.GridPanel();
public Ext.Net.Store MitarbeiterStore = new Ext.Net.Store();
public Ext.Net.JsonReader MitarbeiterJSONReader = new Ext.Net.JsonReader();
public Ext.Net.ColumnModel MitarbeiterColumnModel = new Ext.Net.ColumnModel();
public MitarbeiterUndTelefonliste()
{
}
protected void Page_Load(object sender, EventArgs e)
{
MitarbeiterDataSource.ID = "MitarbeiterDataSource";
MitarbeiterDataSource.ContextTypeName = "MitarbeiterlisteEntities";
MitarbeiterDataSource.TableName = "Mitarbeiterliste";
MitarbeiterGridPanel.ID = "MitarbeiterGridPanel";
MitarbeiterGridPanel.Title = "MitarbeiterListe";
MitarbeiterGridPanel.AutoWidth = true;
MitarbeiterGridPanel.Frame = true;
MitarbeiterGridPanel.Height = 570;
MitarbeiterStore.ID = "MitarbeiterStore";
MitarbeiterStore.DataSource = MitarbeiterDataSource;
MitarbeiterColumnModel.ID = "MitarbeiterColumnModel";
MitarbeiterColumnModel.Columns.Add(new Ext.Net.Column() { DataIndex = "primaerschluessel", Header = "Index", Width = 50 });
MitarbeiterJSONReader.Fields.Add(new Ext.Net.RecordField() { Name = "primaerschluessel" });
MitarbeiterGridPanel.Store.Add(MitarbeiterStore);
this.Form.Controls.Add(MitarbeiterGridPanel);
}
}
}
Thanks in advance for any help! I appreciate any suggestions, critics and any help!
You can't assign some column model to the grid. Because it's read-only property.
You have to use MitarbeiterGridPanel.ColumnModel.Columns.Add() instead of MitarbeiterColumnModel.Columns.Add()