ExpandableListView in iOS - mono

I am trying to get my brain around what I can and can't reasonably do UI-wise in a multi-platform app. Initially we are only concerned about iOS and Android, but may need a mobile Windows version eventually.
The specific question is: How do I replicate the Android ExpandableListView functionality in iOS? I've tried a few searches, but haven't found a hint. The key I need is collapsible sections. Is that doable with an iOS listview? If so, do you have/know of an example?
The related non-specific question is: What advice do you have for someone just starting out developing in multimobilemono? I've been working from Greg Shackles' excellent book, "Mobile Development in C#" (which has been wildly helpful!), so I've got some basics. But I'm sure there are some hidden landmines when you get into more complex UI design. Any advice would be greatly appreciated.
Thank you!

You can use the UITableView, and merely change the size of your cell to display more content as needed.
Let us discuss DialogViewController (part of MonoTouch.Dialog) which simplifies the setup of a UITableView.
What you could do is create a UIView that contains both the content, and the expanded content. It would be controller with some property, for example:
bool expanded;
public bool Expanded { get { return expanded; }}
set {
if (expanded == value)
return;
Frame = ComputeSize (value);
expanded = value;
}
}
Then, create a UIViewElement:
new RootElement ("My Root") {
new Section () {
new UIViewElement (new MyView ());
}
}

For your first question, perhaps you could try :
https://github.com/OliverLetterer/SLExpandableTableView

Related

iOS Navigation Bar Prefers Large Titles Scroll Behaviour

In iOS 11 the system apps all compress the navigation bar as you scroll down if you enable prefersLargeTitles:
I can't figure out how to implement this in my own apps though, the bar stays the same by default:
The only thing I can see is Hide Bars On Swipe, but that hides the whole bar rather than compressing it:
This is just an empty project created in Xcode 9 beta and with a new storyboard added.
What do I need to do to get the same behaviour as the system apps?
Don't set anything regarding Large Titles in Interface Builder / Storyboard, only in code. That worked for me.
So in the navigation bar in storyboards, Prefers Large Titles unchecked.
In your view controller:
self.navigationController?.navigationBar.prefersLargeTitles = true
It seems like this issue is happening to people for different reasons. None of the above answers helped me, but here's what DID work...
I deconstructed my app to find the cause, which was the view hierarchy in the storyboard. It appears that the UITableView view HAS to the the first view in your view controller. I had a UITableView with two UIImageViews behind it and that's what was causing the issue. Once I removed those UIImageViews everything worked correctly.
My fix: I ended up creating a UIView in code, adding my two image views to that, THEN adding that UIView to the UITableview.backgroundView.
Hope this helps someone.
If you have to target older iOS versions, you’ll also have to wrap the assignment in an availability check:
if #available(iOS 11, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.topItem?.title = "Hello"
navigationController?.navigationItem.largeTitleDisplayMode = .automatic
let attributes = [
NSAttributedStringKey.foregroundColor : UIColor.red,
]
navigationController?.navigationBar.largeTitleTextAttributes = attributes
} else {
// Fallback on earlier versions
}
http://iosrevisited.blogspot.in/2017/09/navigation-bar-with-large-titles-and.html

Starting with Kinect for Windows - SDK 1.7

I'm starting with Kinect SDK 1.7, using KinectRegion and other controls like KinectTileButton and KinectScrollViewer from the toolkit. My questions are:
How to enable KinectRegion to work with left and right hands?
Does the SDK 1.7 have something ready to work with zooming?
How to detect grip and release?
Any code available on the Internet?
Thank you!
To Enable the Kinect Region :
Import "Microsoft.Kinect.Toolkit.Controls" project into your solution. (Use Add -> Existing Project)
Add Reference of "Microsoft.Kinect.Toolkit.Controls" into your project.
Add KinectRegion into your XAML using this code :
Import/Use "Microsoft.Kinect.Toolkit.Controls" in your xaml.cs file :
using Microsoft.Kinect.Toolkit;
Bind the sensor chooser's current sensor to the KinectRegion :
var regionSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
BindingOperations.SetBinding(this.kinectRegion, KinectRegion.KinectSensorProperty,
regionSensorBinding);
I don't get what you mean about "zooming". Please give more detail.
To detect hand gripping and hand release, you can add "AddHandPointerGripHandler" and "AddHandPointerGripReleaseHandler" to your KinectRegion. Please take a look to the KinectScrollViewer.cs.
You can explore the code about the hand pointer and stuff from the "Kinect Developer Toolkit Browser App".
As far as I can remember, KinectRegion works with both hand and automatically detects which one is the main one.
The grip and release detection is also automatic on KinectScrollViewer controls.
About the zooming I have no idea.
You'll find good tutorial on Kinect SDK 1.7 Interactions features on this link
Absolutely outstanding course is on the links below:
The first part shows the basic of Kinect SDK
The second part is similiar to firs part, but with use of MS Blend
And the third part is tutorial for interaction stream, where you can get information of both hands.
But if you´d like to use both hand at Kinect region, you have to edit Microsoft.Kinect.Toolkit.Controls -> KinectRegion.cs -> line 1000 (more info in MSDN Blog question)
It helped to me! (I have the same problem)!
For Grip detection is available in kinectRegion -> kinectRegion.HandPointers[idex of hand(0 is left, 1 is right)].IsInGripInteraction - it´s bool - I added some code:
private Skeleton []skeleton;
private void kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame sf = e.OpenSkeletonFrame())
{
if (sf != null && this.skeleton != null) // check that a frame is available
{
sf.CopySkeletonDataTo(this.skeleton); // get the skeletal information in this frame
}
}
}
sensor.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(kinect_SkeletonFrameReady);
foreach (var sk in skeleton)
{
if (sk.TrackingId == 0) continue;
else
{
if (kinectRegion.HandPointers[0].IsInGripInteraction == true)
{
.......
}
}
}

View Switch doesn't work with 51Degrees

I have got a MVC4 application where I used 51Degrees (Lite) to detect device and accordingly select the mobile (.mobile.cshtml) or desktop (.cshtml) view. 51Degrees can properly do that job. However if I want to switch from Mobile to Desktop view (on a mobile device) using HttpContext.SetOverriddenBrowser(BrowserOverride.Desktop) it doesn't work. FYI, it works without 51Degrees.
Here is the code to select display mode (Application_Start() in Global.asax.cs):
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("mobile")
{ContextCondition = Context =>Context.Request.Browser["IsMobile"] == "True"
});
Here is the view switcher controller action code:
public class ViewSwitcherController : Controller
{
public RedirectResult SwitchView(bool mobile, string ReturnUrl="/Login/Login")
{
// If the mobile user has requested to view the mobile view
// remove any overridden user agent for the current request
if (Request.Browser.IsMobileDevice == mobile)
HttpContext.ClearOverriddenBrowser();
else
// Otherwise override the browser setting to desktop mode
HttpContext.SetOverriddenBrowser(mobile ? BrowserOverride.Mobile : BrowserOverride.Desktop);
return Redirect(ReturnUrl);
}
}
Here is the code in the view to switch to Desktop view:
#Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, ReturnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
Please let me know if I'm missing something.
Thanks in advance.
Sorry for my long delayed answer.
The following solution was provided by one of the developers at 51Degrees:
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("mobile")
{
ContextCondition = Context => Context.GetOverriddenBrowser()["IsMobile"] == "true"
});
So replacing Context.Request.Browser["IsMobile"] with Context.GetOverriddenBrowser()["IsMobile"] fixes my problem.
Hope that helps.
I know this is a bit dated, but I ran into this tonight. Same symptoms. Works without Mobi51, does not with. My working theory is that Request.Browser.IsMobileDevice is touched by Mobi51 and it takes control of that property and sets its value regardless of what you would expect .NET to do with it.
My current solution is this. When I check in my viewstart file to switch layouts I check that both Request.Browser.IsMobileDevice and Context.GetOverridenBrowser().IsMobileDevice are true.
When it's truly Mobile, both will be true. When it's truly desktop, both are false. When it's a mobile view requesting desktop, Request.Browser.IsMobileDevice will be true (because Mobi51 says so) and Context.GetOverridenBrowser().IsMobileDevice will be false. Here's my viewstart
#{
Layout = Request.Browser.IsMobileDevice && Context.GetOverriddenBrowser().IsMobileDevice
? "~/Views/Shared/_LayoutMobile.cshtml"
: "~/Views/Shared/_Layout.cshtml";
}
I'm still vetting this and have to add desktop to mobile switching still (which I can already see a problem, but the change to make that direction work as well is easy enough , but in my five minutes of testing so far tonight this has worked. I'm curious if you found another reason/way to work with this, or if this solution is satisfactory for you.

How do I dynamically change the height of a TableViewRow?

Application Type: mobile
Titanium SDK: 3.1.0.GA
Platform & version: iOS 6.1
Device: iOS Simulator
Host Operating System: OSX 10.8.3
Titanium Studio: 3.1.0.201304151600
I'd like to conditionally show/hide a textfield in a TableViewRow. In order to do this I need to expand the height of the row. The following code doesn't work, though. The TableViewRow is actually an Alloy controller. I first tried animating it before I realized that it can't be animated. Now I'm just trying to change the height and that isn't even working. I've tried using the setHeight method along with just setting the height property directly to no avail.
Any ideas?
var notesVisible = false;
function notes_click() {
if(notesVisible == false) {
Ti.API.info('expanding');
$.row.height = 200;
// $.notes_container.setHeight(124);
notesVisible = true;
} else {
Ti.API.info('contracting');
$.row.height = 75;
$.notes_container.setHeight(0);
notesVisible = false;
}
};
There are two good ways of doing this, both should be done from the click event listener.
Method 1) One way is to directly change the "height" variable of the row
Method 2) The second is to create a new row and replace the current row with the new row
Method 1 is more straightforward but I found it to be glitchy depending on what version of the SDK you are using, but with 3.1.0 it should work. Both methods should be called from the 'click' eventListener as its easier to tell Titanium which row to act on based on the click
So here is an example
currentTableview.addEventListener('click',function(e)
{
// DO whatever your row is supposed to do when clicked
// Now lets change the height of the row to a new height, 200 in this example
e.row.height = 200
}
With Method two, it involves creating a new row and then replacing the current row with this call
currentTableview.updateRow(e.index,newlyCreatedUpdatedRow);
I know its an old question asked by some one but the solution provided will not work and i think best solution for this is by making a recursive function and changes the height of your row and need to play with the visibility of views inside that row hopefully will help someone :)

Tapku Coverflow: Programmatically change image

i'm trying to implement a button to increment the album art using Tapku Library and not having much luck.
I was considering replicating a touch using 'touchesBegan' but this is a bit hacky and would rather a cleaner approach.
My code to increment the image, which does not update the image is as follows:
(IBAction)nextImage:(id)sender {
if(imageSelected++ < kNumberOfImages){
coverView.image = [imagesArray objectAtIndex:imageSelected];
[self coverflowView:coverFlow coverAtIndexWasBroughtToFront:imageSelected];
}else{
imageSelected--;
}
}
Can anyone tell me where i might be going wrong? Thanks