Can't I use await animation on Device.StartTimer()? - xamarin.ios

I'm making app with Xamarin.forms pcl.
If I use UIRefreshControl with Scrollview on iOS and animation same time.
It crash!
Is this bug of UIRefreshControl?
I provide reproduce sample code here.
https://github.com/myallb/test_pulltorefresh.git
Sample code is very simple.
Is there any mistake??
Thanks.
public partial class testPage : ContentPage
{
public PullToRefreshLayout RefreshView = null;
AbsoluteLayout layout;
public testPage()
{
InitializeComponent();
layout = new AbsoluteLayout()
{
BackgroundColor = Color.Purple,
};
ScrollView scrollview = new ScrollView()
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Content = layout
};
RefreshView = new PullToRefreshLayout
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Content = scrollview,
RefreshColor = Color.Red,
RefreshCommand = new Command(RefreshStart)
};
RefreshView.IsPullToRefreshEnabled = true;
Content = RefreshView;
Device.StartTimer(new TimeSpan(0, 0, 1), ani);
}
bool ani()
{
Label z = new Label()
{
Text = "Z",
TextColor = Color.White,
FontAttributes = FontAttributes.Bold,
FontSize = new Random().Next(22, 35)
};
AbsoluteLayout.SetLayoutBounds(z, new Rectangle(0.67 + new Random().Next(0, 10) / 100.0, 0.13 + new Random().Next(0, 10) / 100.0, 40, 40));
AbsoluteLayout.SetLayoutFlags(z, AbsoluteLayoutFlags.PositionProportional);
layout.Children.Add(z);
Device.BeginInvokeOnMainThread(async () =>
{
Task t1 = z.FadeTo(0, 3500);
Task t2 = z.TranslateTo(0, -70, 3500, Easing.SinInOut);
await Task.WhenAll(t1, t2);
layout.Children.Remove(z);
});
return true;
}
void RefreshStart()
{
Debug.WriteLine("RefreshStart");
if (RefreshView != null)
RefreshView.IsRefreshing = true;
Device.BeginInvokeOnMainThread(async () =>
{
await Task.Delay(20);
Debug.WriteLine("RefreshEnd");
RefreshView.IsRefreshing = false;
});
}
}

Related

Jetpack Compose view position and shadow preview is different to on when running on device

I have the below code, however the Preview is rendering the view different to when I run it on a AVD (Android Virtual Device). It looks there are 2 things different:
Firstly, the AVD is rending the view at the top of the screen, but the preview is rending the view in the centre of the screen. I've added contentAlignment = Alignment.Center to my AlertView Box which I believe should render it in the middle of the screen.
Secondly, the AVD is showing a weird shadow compared to the preview.
Images below of the preview and AVD:
//Preview Provider
#Preview(
showSystemUi = true,
device = Devices.PIXEL_4_XL,
uiMode = Configuration.UI_MODE_NIGHT_NO,
showBackground = true,
backgroundColor = 0xFFFFFFFF
)
#Preview(
showSystemUi = true,
device = Devices.PIXEL_4,
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
backgroundColor = 0xFF000000
)
#Composable
fun DefaultPreview() {
AlertView()
}
//AlertViewModel
class AlertViewModel : ViewModel() {
var showAlert: Boolean by mutableStateOf(false)
var alertIcon: ImageVector by mutableStateOf(Icons.Rounded.WifiOff)
var alertTitle: String by mutableStateOf("No internet connection")
var alertMessage: String by mutableStateOf("This is the alert message and it is purposely longer than one line to be displayed on screen")
var alertButtonText: String by mutableStateOf("This is the alert button text")
}
//--------------------------------------------------------------------------------------------------
//.onCreate
class AlertManager : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AlertView()
}
}
}
//AlertView
#Composable
fun AlertView(alertViewModel: AlertViewModel = viewModel()) {
Box(
contentAlignment = Alignment.Center
) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.padding(30.dp, 0.dp)
.background(
shape = RoundedCornerShape(15.dp),
color =
if (isSystemInDarkTheme()) {
Color.Black
} else {
Color.White
}
)
.shadow(
elevation = 1.dp,
shape = RoundedCornerShape(15.dp),
ambientColor = if (isSystemInDarkTheme()) {
Color.Black
} else {
Color.White
},
spotColor = if (isSystemInDarkTheme()) {
Color.White
} else {
Color.Gray
},
)
.padding(30.dp, 25.dp),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(20.dp)
) {
Icon(
imageVector = alertViewModel.alertIcon,
contentDescription = null,
tint = if (isSystemInDarkTheme()) {
Color.White
} else {
Color.Black
},
)
Text(
text = alertViewModel.alertTitle,
style = TextStyle(
fontSize = 20.sp,
fontWeight = FontWeight.SemiBold,
color = if (isSystemInDarkTheme()) {
Color.White
} else {
Color.Black
}
)
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(25.dp),
) {
Text(
text = alertViewModel.alertMessage,
color = if (isSystemInDarkTheme()) {
Color.White
} else {
Color.Black
}
)
Button(
onClick = {
alertViewModel.showAlert = false
},
colors = ButtonDefaults.buttonColors(
backgroundColor = if (isSystemInDarkTheme()) {
Color.White
} else {
Color.Black
}
),
shape = RoundedCornerShape(15.dp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp),
contentPadding = PaddingValues(15.dp),
) {
Text(
text = alertViewModel.alertButtonText,
fontWeight = FontWeight.Bold,
color = if (isSystemInDarkTheme()) {
Color.Black
} else {
Color.White
}
)
}
}
}
}
}

How I can Add Text inside Frame TabbedRenderer in Xamarin iOS

I am customizing Badge in TabbedPage. I have now added the red dot from inheriting UIView. However how can I Add Text inside that Frame. Xamarin iOS
MyTabbedPageRenderer.cs
public static class TabbarExtensions
{
readonly static int tabBarItemTag = 9999;
public static void addItemBadge(this UITabBar tabbar, int index)
{
if (tabbar.Items != null && tabbar.Items.Length == 0) return;
if (index >= tabbar.Items.Length) return;
removeItemBadge(tabbar, index);
var badgeView = new UIView();
badgeView.Tag = tabBarItemTag + index;
badgeView.Layer.CornerRadius = 7;
badgeView.BackgroundColor = UIColor.Red;
var tabFrame = tabbar.Frame;
var percentX = (index + 0.56) / tabbar.Items.Length;
var x = percentX * tabFrame.Width;
var y = tabFrame.Height * 0.05;
badgeView.Frame = new CoreGraphics.CGRect(x, y, 13, 13);
tabbar.AddSubview(badgeView);
//var badgeView = new UILabel();
//badgeView.Tag = tabBarItemTag + index;
//badgeView.BackgroundColor = UIColor.Red;
//var tabFrame = tabbar.Frame;
//var percentX = (index + 0.56) / tabbar.Items.Length;
//var x = percentX * tabFrame.Width;
//var y = tabFrame.Height * 0.05;
//badgeView.Text = "1";
//badgeView.TextAlignment = UITextAlignment.Center;
//badgeView.TextColor = UIColor.White;
//badgeView.Font = UIFont.SystemFontOfSize(10);
//tabbar.AddSubview(badgeView);
}
public static bool removeItemBadge(this UITabBar tabbar, int index)
{
foreach (var subView in tabbar.Subviews)
{
if (subView.Tag == tabBarItemTag + index)
{
subView.RemoveFromSuperview();
return true;
}
}
return false;
}
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
MessagingCenter.Subscribe<object, int>(this, "Add", (obj, index) => {
TabBar.addItemBadge(index);
});
MessagingCenter.Subscribe<object, int>(this, "Remove", (obj, index) => {
TabBar.removeItemBadge(index);
});
}
MainView.xaml.cs
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send<object, int>(this, "Add", 2);
}
As in my code above I tried with UILabel. However I cannot set CornerRadius for Label
Summarize how I can Add Text inside Frame. Or how can I set CornerRadius for Lable in Xamarin iOS.
Thank you!
Description picture:
If I use UILabel, I cannot set CornerRadius
If I use UIView
For UILabel, you could set the CornerRadius using the following:
badgeView.Layer.CornerRadius = 7;
badgeView.Layer.MasksToBounds = true;//add this line
For more info, you could refer to masksToBounds.
Hope it works for you.

Creating a 2D Snapshot using three JS library inside Node JS

I'm using the below code to create 3D model using the Three JS library. Code was running successfully in node JS, but when I'm trying to save an image, I'm getting output as a blank image.
I do have a ThreeUtil JS file which is holding the constants of my shader materials and a couple of functions. There is no problem with this utility file
Observation: I see my buffer data with all element values as zero itself. Can someone let me know where exactly I'm going wrong with my implementation?
Please find the code in below sandbox URL
https://codesandbox.io/s/boring-lewin-7msxm
Attached sample input file as sampleinput.json . from an endpoint need to class main typescript file which will perform the creation and capturing screenshot
import Jimp from 'jimp';
const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const THREE = require('three');
const THREESTLLoader = require('three-stl-loader');
const THREEObjLoader = require('three-obj-loader');
const jsdom = require('jsdom');
const gl = require('gl');
import { WebGLRenderTarget } from 'three';
const HOMUNCULUS_OBJ_URL = './assets/3d-homunculus.obj';
const Canvas = require('canvas');
export class ThreeDimensionalModel {
private prostateMeshData: ProstateMeshData;
private width: number = 660;
private height: number = 660;
private dimensions: ThreeCanvasDimensions;
private scenes: Scenes;
private camera: THREE.PerspectiveCamera;
private matrix: THREE.Matrix4;
private rotationMatrix: THREE.Matrix4;
private prostateMeshBoundingBox: THREE.Box3;
private renderer: THREE.WebGLRenderer;
constructor() {
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
// #ts-ignore
global.window = window;
// #ts-ignore
global.document = document;
// #ts-ignore
global.window.decodeURIComponent = global.decodeURIComponent;
// Adding XML HTTP Requests library
// #ts-ignore
global.XMLHttpRequest = XMLHttpRequest;
this.dimensions = this.calculateDimensions();
this.scenes = this.initializeScenes();
this.camera = this.initializeCamera();
this.decorateScenes();
this.loadModels(this.prostateMeshData);
this.renderer = this.createRenderer();
this.animate();
}
private calculateDimensions = (): ThreeCanvasDimensions => ({
width: this.width,
height: this.height,
aspect: this.width / this.height,
})
private initializeScenes = (): Scenes => ({
main: new THREE.Scene(),
homunculus: new THREE.Scene(),
})
private initializeCamera(): THREE.PerspectiveCamera {
const camera = new THREE.PerspectiveCamera(
70,
this.dimensions.aspect,
1,
10000);
camera.position.z = 100;
return camera;
}
private decorateScenes(): void {
const ambientLight = new THREE.AmbientLight(0x505050);
const spotLight = this.getSpotLight();
const plane = this.getPlane();
ThreeUtil.addObjectToAllScenes(this.scenes, spotLight);
ThreeUtil.addObjectToAllScenes(this.scenes, ambientLight);
ThreeUtil.addObjectToAllScenes(this.scenes, plane);
}
private loadModels(prostateMeshData: ProstateMeshData): void {
const loader = new THREESTLLoader(THREE);
const dataUri = `data:text/plain;base64,${prostateMeshData.prostateMeshUrl}`;
loader.prototype.load(dataUri, (geometry: THREE.Geometry) => {
this.setModelMatricesAndProstateMeshBoundings(geometry);
this.setupHomunculusMesh();
const prostateMesh = this.createProstateMesh(geometry);
let biopsyMeshes;
if (prostateMeshData.biopsies) {
biopsyMeshes = this.createBiopsyMeshes(prostateMeshData.biopsies);
}
if (prostateMeshData.rois) {
this.loadRoiMeshesOnScene(prostateMeshData.rois);
}
this.addToMainScene(prostateMesh);
if (prostateMeshData.biopsies) {
biopsyMeshes.forEach(biopsyMesh => this.addToMainScene(biopsyMesh));
}
this.scaleInView();
});
}
public saveAsImage() {
// after init of renderer
const renderTarget = new WebGLRenderTarget(this.width, this.height);
const target = this.renderer.getRenderTarget() || renderTarget;
const size = this.renderer.getSize();
// #ts-ignore
target.setSize(size.width, size.height);
this.renderer.setRenderTarget(renderTarget);
this.renderer.render( this.scenes.main, this.camera, target );
// retrieve buffer from render target
const buffer = new Uint8Array(this.width * this.height * 4);
this.renderer.readRenderTargetPixels(renderTarget, 0, 0, this.width, this.height, buffer);
// create jimp image
const image = new Jimp({
data: buffer,
width: this.width,
height: this.height
}, (err: any, images: any) => {
images.write('output.jpeg');
});
}
private createRenderer(): THREE.WebGLRenderer {
const canvasWidth = 1024;
const canvasHeight = 1024;
const canvas = new Canvas.Canvas(canvasWidth, canvasHeight);
canvas.addEventListener = () => {
// noop
}
canvas.style = {};
const renderer = new THREE.WebGLRenderer({ context: gl(this.width, this.height), canvas , preserveDrawingBuffer: true , alpha: true});
renderer.autoClear = false;
renderer.setClearColor(0xFFFFFF);
renderer.setPixelRatio(2);
renderer.setSize(this.dimensions.width, this.dimensions.height);
renderer.sortObjects = false;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
return renderer;
}
private getPlane = (): THREE.Mesh => new THREE.Mesh(
new THREE.PlaneBufferGeometry(2000, 2000, 8, 8),
new THREE.MeshBasicMaterial({ visible: false })
)
private animate = (): void => {
this.renderScenes();
}
private getSpotLight(): THREE.SpotLight {
const spotLight = new THREE.SpotLight(0xffffff, 1.5);
spotLight.position.set(0, 500, 2000);
spotLight.castShadow = true;
spotLight.shadow.camera.near = 200;
spotLight.shadow.camera.far = this.camera.far;
spotLight.shadow.camera.fov = 50;
spotLight.shadow.bias = -0.00022;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
return spotLight;
}
private setModelMatricesAndProstateMeshBoundings(geometry: THREE.Geometry): void {
geometry.computeFaceNormals();
geometry.computeBoundingBox();
// A transformation matrix (matrix) is applied to prostate segmentation, target and biopsy,
// which contains a translation and a rotation
// The translation shifts the center of segmentation mesh to view center
this.prostateMeshBoundingBox = geometry.boundingBox.clone();
const center = this.prostateMeshBoundingBox.getCenter(new THREE.Vector3());
const translationMatrix = new THREE.Matrix4().makeTranslation(-center.x, -center.y, -center.z);
// The default view (DICOM coordinate) is patient head pointing towards user.
// We like patient foot pointing towards user.
// Therefore a 180 degree rotation along x (left-right) axis is applied.
const rotAxis = new THREE.Vector3(1, 0, 0);
this.rotationMatrix = new THREE.Matrix4().makeRotationAxis(rotAxis, Math.PI);
// matrix is the multiplication of rotation and translation
this.matrix = new THREE.Matrix4().multiplyMatrices(this.rotationMatrix, translationMatrix);
}
private createProstateMesh(geometry: THREE.Geometry): THREE.Mesh {
const shaderMaterial = ThreeUtil.createShaderMaterial(new THREE.Vector4(0.8, 0.6, 0.2, 0));
geometry.computeFaceNormals();
geometry.computeBoundingBox();
// A transformation matrix (matrix) is applied to prostate segmentation, target and biopsy,
// which contains a translation and a rotation
// The translation shifts the center of segmentation mesh to view center
this.prostateMeshBoundingBox = geometry.boundingBox.clone();
const mesh = new THREE.Mesh(geometry, shaderMaterial);
mesh.applyMatrix(this.matrix);
mesh.name = 'prostate';
return mesh;
}
private renderScenes(): void {
this.renderer.clear();
this.renderer.setViewport(-150, 0, 210, 75);
this.renderer.render(this.scenes.homunculus, this.camera);
this.renderer.clearDepth();
this.renderer.setViewport(0, 0, this.dimensions.width, this.dimensions.height);
this.renderer.render(this.scenes.main, this.camera);
}
private toCameraCoordinates(position: THREE.Vector3): THREE.Vector3 {
return position.applyMatrix4(this.camera.matrixWorldInverse);
}
private scaleInView(): void {
const point1 = this.toCameraCoordinates(this.prostateMeshBoundingBox.min);
const point2 = this.toCameraCoordinates(this.prostateMeshBoundingBox.max);
this.camera.fov = ThreeUtil.angleInDegree(point1, point2, this.camera) * 2;
this.camera.updateProjectionMatrix();
}
private createBiopsyMeshes(biopsiesMeshData: BiopsyMeshData[]): THREE.Mesh[] {
return biopsiesMeshData.map((biopsyMeshData: BiopsyMeshData, index: number) => {
const startPoint = new THREE.Vector3(
biopsyMeshData.proximalX,
biopsyMeshData.proximalY,
biopsyMeshData.proximalZ
);
const endPoint = new THREE.Vector3(biopsyMeshData.distalX, biopsyMeshData.distalY, biopsyMeshData.distalZ);
const color = biopsyMeshData.adenocarcinoma ?
0x0000ff: 0x002233;
const opacity = biopsyMeshData.adenocarcinoma ? 0.65 : 0.3;
const material = new THREE.MeshLambertMaterial({
transparent: true,
depthWrite: false,
depthTest: false,
emissive: new THREE.Color(color),
opacity,
});
const cylinder = ThreeUtil.getCylinderBetweenPoints(startPoint, endPoint, material);
cylinder.applyMatrix(this.matrix);
cylinder.name = `biopsy_${index}`;
return cylinder;
});
}
private loadRoiMeshesOnScene(roisMeshData: RoiMeshData[]): void {
roisMeshData.forEach((roiMeshData: RoiMeshData, index: number) => this.setupRoiMesh(roiMeshData, index));
}
private setupRoiMesh(roiMeshData: RoiMeshData, index: number): void {
const loader = new THREESTLLoader(THREE);
const dataUri = `data:text/plain;base64,${roiMeshData.ROIMeshUrl}`;
if (roiMeshData.tooltipConfiguration) {
if (typeof(roiMeshData.tooltipConfiguration) === 'string' ) {
roiMeshData.tooltipConfiguration = JSON.parse(roiMeshData.tooltipConfiguration);
}
}
loader.prototype.load(dataUri, (roiGeometry: THREE.Geometry) => {
const color = new THREE.Color(0xA396CB);
const colorVector = new THREE.Vector4(color.r, color.g, color.b, 0);
const shaderMaterial = ThreeUtil.createShaderMaterial(colorVector, roiMeshData.adenocarcinoma);
const mesh = new THREE.Mesh(roiGeometry, shaderMaterial);
mesh.name = `roi_${roiMeshData.ROIId}`;
roiGeometry.applyMatrix(this.matrix);
this.addToMainScene(mesh);
this.saveAsImage();
});
}
private setupHomunculusMesh(): void {
new THREEObjLoader(THREE);
new THREE.OBJLoader().load(HOMUNCULUS_OBJ_URL, (group: THREE.Group) => {
group.traverse((child) => {
if (child instanceof THREE.Mesh) {
// apply custom material
// #ts-ignore
child.material = new THREE.MeshPhongMaterial({
color: 0xb09b70,
specular: 0x050505,
shininess: 100,
flatShading: false
});
const homunculusMatrix = new THREE.Matrix4();
homunculusMatrix.makeScale(0.020, 0.020, 0.020);
homunculusMatrix.multiply(this.rotationMatrix);
child.applyMatrix(homunculusMatrix);
}
});
this.scenes.homunculus.add(group);
});
}
private addToMainScene(object3D: THREE.Object3D): void {
this.scenes.main.add(object3D);
// Adding Ambient Light for all scenes inside main scenes except Humanoid
const ambientLight = new THREE.AmbientLight(0x000000);
this.scenes.main.add(ambientLight);
}
}

How to display container contains tablelayout of 7 columns in center of the screen for all resolution screens in code name one

Currently we are displaying the container that contains the table layout with 7 columns in center of the screen in the 1280x800 pixels resolution.
But we need the same container displaying in the 1920x1200 pixels resolution in center of the screen.
Actually the container is displayed but the row data is missing. Is anything wrong in my code? Please help me how to resolve this one.
FlowLayout centerLayout = new FlowLayout();
centerLayout.setAlign(Component.CENTER);
centerLayout.setValign(Component.TOP);
Container centerContainer = new Container(centerLayout);
topTabelcontainer = new Container(new TableLayout(7, 1));
commonComponentsForm = new CommonComponentsForm();
eventPostSchedulesForm = commonComponentsForm.setEventPostSchedulesFormHeader(eventPostSchedulesForm, res, workerBreaksPreferences);
topTabelcontainer = commonComponentsForm.getEventInfoHeader(eventPostSchedulesForm, res, topTabelcontainer, "showroster");
filterLayoutContainer = this.getFilterBody();
postScheduleTableContainer = this.getEventPostScheduleTable();
TableLayout.Constraint postScheduleTableConstraint = new TableLayout.Constraint();
postScheduleTableConstraint.setHorizontalAlign(BorderLayout.CENTER_BEHAVIOR_SCALE);
postScheduleTableConstraint.setVerticalAlign(BorderLayout.CENTER_BEHAVIOR_SCALE);
topTabelcontainer.add(filterLayoutContainer);
headerContainer);
topTabelcontainer.add(postScheduleTableConstraint, postScheduleTableContainer);
centerContainer.add(topTabelcontainer);
centerContainer.setScrollableY(Boolean.TRUE);
centerContainer.setTactileTouch(Boolean.TRUE);
centerContainer.addPointerDraggedListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
float val = Display.getInstance().getDragSpeed(false);
boolean upperFlag = false;
if (Display.getInstance().isPortrait()) {
if (portRaitUpperBound < toralRecourdsCount)
upperFlag = true;
} else if (landScapeUpperBound < toralRecourdsCount)
upperFlag = true;
boolean lowerFlag = false;
if (Display.getInstance().isPortrait()) {
if ((portRaitLowerBound > 0 && portRaitLowerBound <= toralRecourdsCount))
lowerFlag = true;
} else if (landScapeLowerBound > 0 && landScapeLowerBound < toralRecourdsCount)
lowerFlag = true;
if (val >= 0.5 && scrollFlag) {
dragFlag = true;
if (upperFlag) {
scrollFlag = false;
setPageUpperAndLowerBound(Constants.NEXTFLAG);
postScheduleTableContainer.removeAll();
setEventPostScheduleTable(postScheduleTableContainer);
eventPostSchedulesForm.revalidate();
}
} else if (val <= -0.5 && scrollFlag) {
dragFlag = true;
if (lowerFlag) {
scrollFlag = false;
setPageUpperAndLowerBound(Constants.PREVIOUSFLAG);
postScheduleTableContainer.removeAll();
setEventPostScheduleTable(postScheduleTableContainer);
eventPostSchedulesForm.revalidate();
}
}
}
});
eventPostSchedulesForm.setUIID("workersListForm");
eventPostSchedulesForm.add(BorderLayout.CENTER, centerContainer);
commonComponentsForm.getFooterTag(eventPostSchedulesForm);
eventPostSchedulesForm.show();
}
public Container getEventPostSchedulesTableHeader(Container postSchedulesTableHeaderContainer) {
Label position = new Label(Constants.POSITION, searchingButtonImage);
Label name = new Label(Constants.NAME, searchingButtonImage);
Label callInOutLabel = new Label(Constants.CALLINOUT);
position.setTextPosition(LEFT);
name.setTextPosition(LEFT);
TextArea actualCallIn1 = null;
Label actualCallIn = null;
TextArea actualCallOut1 = null;
Label actualCallOut = null;
TextArea agencyWorker1 = null;
Label agencyWorker = null;
if (Display.getInstance().isPortrait()) {
actualCallIn1 = new TextArea(Constants.ACTUALCALLIN);
actualCallIn1.setEditable(false);
actualCallIn1.setFocusable(false);
actualCallIn1.setColumns(3);
actualCallIn1.setVerticalAlignment(Component.CENTER);
actualCallOut1 = new TextArea(Constants.ACTUALCALLOUT);
actualCallOut1.setEditable(false);
actualCallOut1.setFocusable(false);
actualCallOut1.setColumns(3);
actualCallOut1.setVerticalAlignment(Component.CENTER);
agencyWorker1 = new TextArea(Constants.AGENCYWORKER);
agencyWorker1.setEditable(false);
agencyWorker1.setFocusable(false);
agencyWorker1.setColumns(3);
agencyWorker1.setVerticalAlignment(Component.CENTER);
} else {
agencyWorker = new Label(Constants.AGENCYWORKER);
actualCallIn = new Label(Constants.ACTUALCALLIN);
actualCallOut = new Label(Constants.ACTUALCALLOUT);
}
Label workerBreak = new Label(" ");
position.setUIID("workerTableHeader");
name.setUIID("workerTableHeader");
callInOutLabel.setUIID("workerTableHeader");
if (Display.getInstance().isPortrait()) {
agencyWorker1.setUIID("workerTableHeader");
actualCallIn1.setUIID("workerTableHeader");
actualCallOut1.setUIID("workerTableHeader");
} else {
agencyWorker.setUIID("workerTableHeader");
actualCallIn.setUIID("workerTableHeader");
actualCallOut.setUIID("workerTableHeader");
}
workerBreak.setUIID("workerTableHeader");
if (Display.getInstance().isPortrait()) {
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(16, 8), position);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(15, 8), name);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(24, 8), callInOutLabel);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(13, 8), actualCallIn1);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(13, 8), actualCallOut1);
postSchedulesTableHeaderContainer.add(getTableConstraint(13, 8), agencyWorker1);
if (workerBreaksPreferences.getAllowbreaks() != null && !"".equals(workerBreaksPreferences.getAllowbreaks()) && "1".equals(workerBreaksPreferences.getAllowbreaks()))
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(6, 8), workerBreak);
} else {
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(13, 10), position);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(18, 10), name);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(20, 10), callInOutLabel);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(13, 10), actualCallIn);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(13, 10), actualCallOut);
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(16, 10), agencyWorker);
if (workerBreaksPreferences.getAllowbreaks() != null && !"".equals(workerBreaksPreferences.getAllowbreaks()) && "1".equals(workerBreaksPreferences.getAllowbreaks()))
postSchedulesTableHeaderContainer.addComponent(getTableConstraint(7, 10), workerBreak);
}
return postSchedulesTableHeaderContainer;
}
public Container getEventPostScheduleTable() {
List < WorkerBean > eventPostSchedulesList = null;
roasterDao = RoasterDao.getInstance();
if (Display.getInstance().isPortrait()) {
eventPostSchedulesList = roasterDao.getEventPostSchedulesDetails(positionFilterValue, nameFilterValue, portRaitLowerBound, portRaitPageSize);
} else {
eventPostSchedulesList = roasterDao.getEventPostSchedulesDetails(positionFilterValue, nameFilterValue, landScapeLowerBound, landScapePageSize);
}
int tableRowCount = Constants.INITIALTABLEROWS;
boolean pagingFlag = false;
int eventPostScheduleCount = roasterDao.getEventPostSchedulesCount(positionFilterValue, nameFilterValue);
this.toralRecourdsCount = eventPostScheduleCount;
FlowLayout centerLayout = new FlowLayout();
centerLayout.setAlign(Component.CENTER);
postScheduleTableContainer = new Container(centerLayout);
postScheduleTableContainer.setUIID("tableBodyContainer");
if (eventPostSchedulesList.size() > landScapePageSize) {
tableRowCount = landScapePageSize + 1;
} else {
tableRowCount = eventPostSchedulesList.size() + 1;
}
Container borderTopPagingContainer = new Container(new BorderLayout());
if (eventPostScheduleCount > landScapePageSize) {
pagingFlag = true;
if (Display.getInstance().isPortrait()) {
borderTopPagingContainer = this.setHeaderPaging(eventPostScheduleCount, portRaitLowerBound, portRaitUpperBound, res);
} else {
borderTopPagingContainer = this.setHeaderPaging(eventPostScheduleCount, landScapeLowerBound, landScapeUpperBound, res);
}
}
if (pagingFlag) {
tableRowCount = tableRowCount + 1;
}
int columnCount = 6;
if (workerBreaksPreferences.getAllowbreaks() != null && !"".equals(workerBreaksPreferences.getAllowbreaks()) && "1".equals(workerBreaksPreferences.getAllowbreaks()))
columnCount++;
Container postSchedulesListContainer = new Container(new TableLayout(tableRowCount, columnCount));
if (pagingFlag) {
TableLayout.Constraint postSchedulesListConstraint1 = new TableLayout.Constraint();
postSchedulesListConstraint1.setHorizontalSpan(columnCount);
postSchedulesListContainer.add(postSchedulesListConstraint1, borderTopPagingContainer);
}
postSchedulesListContainer = this.getEventPostSchedulesTableHeader(postSchedulesListContainer);
String callInDBValue = "";
String callOutDBValue = "";
String actCallInDBValue = "";
String actCallOutDBValue = "";
Label position = null;
Label name = null;
Label callInOutLabel = null;
Label actualCallIn = null;
Label actualCallOut = null;
TextField agencyWorker = null;
Label workerBreak = null;
for (WorkerBean eventPostSchedules: eventPostSchedulesList) {
callInDBValue = "";
if (eventPostSchedules != null) {
if (eventPostSchedules.getCallIn().length() > 10)
callInDBValue = eventPostSchedules.getCallIn().substring(10).trim();
else {
if (Constants.PLATFORMNAME.equals(Display.getInstance().getPlatformName()))
callInDBValue = " ";
else
callInDBValue = " ";
}
}
callOutDBValue = "";
if (eventPostSchedules != null) {
if (eventPostSchedules.getCallOut().length() > 10)
callOutDBValue = eventPostSchedules.getCallOut().substring(10).trim();
else {
if (Constants.PLATFORMNAME.equals(Display.getInstance().getPlatformName()))
callOutDBValue = " ";
else
callOutDBValue = " ";
}
}
actCallInDBValue = "";
if (eventPostSchedules != null) {
if (eventPostSchedules.getActCallIn().length() > 10)
actCallInDBValue = eventPostSchedules.getActCallIn().substring(10).trim();
else
actCallInDBValue = eventPostSchedules.getActCallIn().trim();
}
actCallOutDBValue = "";
if (null != eventPostSchedules) {
if (eventPostSchedules.getActCallOut().length() > 10)
actCallOutDBValue = eventPostSchedules.getActCallOut().substring(10).trim();
else
actCallOutDBValue = eventPostSchedules.getActCallOut().trim();
}
callInDBValue = ((callInDBValue.trim().length() < 8) ? " ".concat(callInDBValue) : callInDBValue) + ((callOutDBValue.trim().equals("")) ? callOutDBValue : " - " + callOutDBValue);
position = new Label(eventPostSchedules.getPersonnelType());
name = new Label(eventPostSchedules.getName());
callInOutLabel = new Label(callInDBValue);
actualCallIn = new Label(actCallInDBValue);
actualCallIn.setFocusable(Boolean.TRUE);
actualCallIn.addPointerPressedListener(createActualCallChangeListener(actualCallIn, eventPostSchedules.getSerialId(), Constants.ACTUALCALLINFLAG, eventPostSchedules.getName(), eventPostSchedules.getActCallIn(), eventPostSchedules.getActCallOut(), eventPostSchedules.getActCallIn()));
actualCallOut = new Label(actCallOutDBValue);
actualCallOut.setFocusable(Boolean.TRUE);
actualCallOut.addPointerPressedListener(createActualCallChangeListener(actualCallOut, eventPostSchedules.getSerialId(), Constants.ACTUALCALLOUTFLAG, eventPostSchedules.getName(), eventPostSchedules.getActCallIn(), eventPostSchedules.getActCallOut(), eventPostSchedules.getActCallOut()));
agencyWorker = new TextField(eventPostSchedules.getAgencyWorker(), null, 5, TextArea.ANY);
position.setUIID("workersList");
name.setUIID("workersList");
callInOutLabel.setUIID("workersList");
actualCallIn.setUIID("workersListEditable");
actualCallOut.setUIID("workersListEditable");
agencyWorker.setUIID("workersListEditable");
workerBreak.setUIID("workersList");
if (Display.getInstance().isPortrait()) {
postSchedulesListContainer.addComponent(getTableConstraint(16, 8), position);
postSchedulesListContainer.addComponent(getTableConstraint(15, 8), name);
postSchedulesListContainer.addComponent(getTableConstraint(24, 8), callInOutLabel);
postSchedulesListContainer.addComponent(getTableConstraint(13, 8), actualCallIn);
postSchedulesListContainer.addComponent(getTableConstraint(13, 8), actualCallOut);
postSchedulesListContainer.addComponent(getTableConstraint(13, 8), agencyWorker);
if (workerBreaksPreferences.getAllowbreaks() != null && !"".equals(workerBreaksPreferences.getAllowbreaks()) && "1".equals(workerBreaksPreferences.getAllowbreaks()))
postSchedulesListContainer.addComponent(getTableConstraint(6, 8), workerBreak);
} else {
postSchedulesListContainer.addComponent(getTableConstraint(13, 10), position);
postSchedulesListContainer.addComponent(getTableConstraint(18, 10), name);
postSchedulesListContainer.addComponent(getTableConstraint(20, 10), callInOutLabel);
postSchedulesListContainer.addComponent(getTableConstraint(13, 10), actualCallIn);
postSchedulesListContainer.addComponent(getTableConstraint(13, 10), actualCallOut);
postSchedulesListContainer.addComponent(getTableConstraint(16, 10), agencyWorker);
if (workerBreaksPreferences.getAllowbreaks() != null && !"".equals(workerBreaksPreferences.getAllowbreaks()) && "1".equals(workerBreaksPreferences.getAllowbreaks()))
postSchedulesListContainer.addComponent(getTableConstraint(7, 10), workerBreak);
}
}
postScheduleTableContainer.add(postSchedulesListContainer);
return postScheduleTableContainer;
}
}
}
public TableLayout.Constraint getTableConstraint(int widthPercent, int heightPercent) {
TableLayout.Constraint tableConstraint = new TableLayout.Constraint();
tableConstraint.setWidthPercentage(widthPercent);
tableConstraint.setHeightPercentage(heightPercent);
return tableConstraint;
}
}
Don't use flow layout for large dynamic data. You border layout with center constraint or absolute center.
Flow layout is overly simplistic and shouldn't be used for complex structures since Codename One doesn't reflow. There is a big discussion of that in the developer guide.

MvvmCross: Cannot add more than one UIPickerView

I'm building an iOS view using Xamarin and MvvmCross and I have come across an interesting little issue. I can't seem to add more than one UIPickerView to a UIView.
Add one view and all works well. Add a second and the simulator just hangs when I try and open the page.
This seems to be related to a UITextField with an InputView as I also have an issue if I try to add a UIDatePicker as well.
Nothing strange in the debug output.
Here is the code:
[Register("EditJobViewJobView")]
public class EditJobView : MvxViewController
{
public new EditJobViewModel ViewModel
{
get { return (EditJobViewModel)base.ViewModel; }
}
private const float _leftMargin = 6;
private const float _labelHeight = 20;
private const float _pickerHeight = 28;
private readonly UIFont _labelFont = UIFont.BoldSystemFontOfSize(18f);
private readonly UIFont _controlFont = UIFont.SystemFontOfSize(18f);
private readonly UIView _paddingInsert = new UIView(new RectangleF(0, 0, 4, 0));
private int _currentTop = 0;
public override void ViewDidLoad()
{
base.ViewDidLoad();
View = new UIView() { BackgroundColor = UIColor.White };
NavigationItem.SetRightBarButtonItem(new UIBarButtonItem("Save", UIBarButtonItemStyle.Bordered,
(sender, args) => ViewModel.OkCommand.Execute(null)), true);
// ios7 layout
if (RespondsToSelector(new Selector("edgesForExtendedLayout")))
EdgesForExtendedLayout = UIRectEdge.None;
Title = "Edit Job";
AddLabel("Job Status");
MvxPickerViewModel jobStatusPickerViewModel;
var jobStatusTextView = AddPickerView(out jobStatusPickerViewModel);
AddLabel("Job Priority");
MvxPickerViewModel jobPriorityPickerViewModel;
var jobPriorityTextView = AddPickerView(out jobPriorityPickerViewModel);
var set = this.CreateBindingSet<EditJobView, EditJobViewModel>();
set.Bind(jobStatusPickerViewModel).For(p => p.SelectedItem).To(vm => vm.SelectedJobStatusType);
set.Bind(jobStatusPickerViewModel).For(p => p.ItemsSource).To(vm => vm.JobStatusTypes);
set.Bind(jobStatusTextView).To(vm => vm.SelectedJobStatusType);
set.Bind(jobPriorityPickerViewModel).For(p => p.SelectedItem).To(vm => vm.SelectedJobPriority);
set.Bind(jobPriorityPickerViewModel).For(p => p.ItemsSource).To(vm => vm.JobPriorities);
set.Bind(jobPriorityTextView).To(vm => vm.SelectedJobPriority);
set.Apply();
}
private void AddLabel(string caption)
{
_currentTop += 10;
var frame = new RectangleF(_leftMargin, _currentTop, 300, _labelHeight);
var label = new UILabel(frame);
label.Font = _labelFont;
label.Text = caption;
AddView(label);
_currentTop += 2;
}
private UITextField AddPickerView(out MvxPickerViewModel pickerViewModel)
{
var textField = AddTextField();
var pickerView = new UIPickerView();
pickerViewModel = new MvxPickerViewModel(pickerView);
pickerView.Model = pickerViewModel;
pickerView.ShowSelectionIndicator = true;
textField.InputView = pickerView;
return textField;
}
private UITextField AddTextField()
{
var frame = new RectangleF(_leftMargin, _currentTop, 300, _pickerHeight);
var textField = new UITextField(frame);
textField.Layer.BorderColor = UIColor.Black.CGColor;
textField.Layer.BorderWidth = 1f;
textField.Font = _controlFont;
textField.LeftView = _paddingInsert;
textField.LeftViewMode = UITextFieldViewMode.Always;
AddView(textField);
return textField;
}
private void AddView(UIView view)
{
View.AddSubview(view);
_currentTop += (int)view.Frame.Height;
}
}
Any ideas?
This was caused by creating a shared padding insert across a number of UITextFields.
To fix this I changed
textField.LeftView = _paddingInsert;
to
textField.LeftView = new UIView(new RectangleF(0, 0, 4, 0));

Resources