Apple Watch Table - First 4 Rows Not Appearing

Proportional table row height for 38mm Apple Watch

Why the rows are cut off

The row heights are intentionally the same, for a couple of reasons.

  • While I don't see a minimum row height mentioned in the design guide, shorter rows would make it harder to target the right row on the 38mm screen. This would lead to an inconsistent user experience between the two watch sizes.

  • A shorter row would lead to the issue of vertically clipping two-line text, which would occur more often on the 38mm screen since the rows are narrower.

    Sample Image

    This example illustrates how the last row's WKInterfaceLabel text descender gets clipped by its group once you reduce the group height for a 38mm screen to fit 4 rows on the screen.

    The shorter row also leads to an insufficient amount of (vertical) white space around the text, making it harder to read rows of content.

Consistent row heights are no different than how some iPhone models can fit more rows per screen compared to some of the smaller-screened devices. Apple doesn't modify the iOS row height to fit the same number of rows on the smaller screen, as could fit on the larger screen. Their watchOS sample code is really consistent with their general design philosophies.

How to accomplish what you ask

You can change the group's height from Default to Fixed, and specify a smaller height (of 34 points) for the 38mm device. This would fit 4 rows on the smaller screen, as illustrated by the previous screen shot:

Sample Image

You should adjust your content as necessary to preserve vertical white space between the content and its group container.

Apple Watch Table on row selected crash

If the crash happens when selecting an item and not when displaying the Table then I would assume it is to do with the row selection code, and would start there.

There are two options here depending on what you are trying todo:

DidSelectRow

Used when the row is selected and you want to manipulate some data or move to another view.

public override async void DidSelectRow(WKInterfaceTable table, nint rowIndex)
{
var contextForNextInterfaceController = rows[(int)rowIndex]; // this depends how you have set up the table.
Console.WriteLine($"Row selected: {rowData}");
PushController("TheNextInterFaceController", contextForNextInterfaceController);
}

GetContextForSegue

Used when you set a segue in iOS Designer or Xcode so you can set the context for the next interface controller you are using.

public override NSObject GetContextForSegue(string segueIdentifier, WKInterfaceTable table, nint rowIndex)
{
// Can check segueIdentifier if using more segues
return new ContextForNextInterfaceController() // This needs to sub class NSObject
{
model = modelForNextInterfaceController,
};
}

When moving to another view after setting the context you will neext to cast the context object and check it is of the type you are looking for:

public override void Awake(NSObject context)
{
base.Awake(context);
Console.WriteLine("{0} awake with context", this);
var currentContext = context as ContextForNextInterfaceController;
if (currentContext != null)
{
// Do stuff with context
}
}

If you could post your Interface Controller code or the row selection code, then I might be able to help more. Also if you are getting any error in the application output that could be helpful too.

===========================================================================
Update

Ok from your error output I would says its the FavoriteRowController thats missing an outlet or wrong class set in the storyboard.

this class is not key value coding-compliant for the key InterfaceTable.'

Is a common error when you are missing a outlet or removed one but not removed the link in the storyboard.

RowControllers dont need to be InterfaceControllers so I would set it up like so:

Code for FavoriteRowController:

using Foundation;

namespace WatchConnectivity.OnWatchExtension
{
public partial class FavoriteRowController : NSObject
{
protected FavoriteRowController()
{
}
}
}

Code for FavoriteRowController.designer.cs:

using Foundation;
using System.CodeDom.Compiler;

namespace WatchConnectivity.OnWatchExtension
{
[Register ("FavoriteRowController")]
partial class FavoriteRowController
{
[Outlet]
public WatchKit.WKInterfaceLabel RowLabel { get; set; }

void ReleaseDesignerOutlets ()
{
if (RowLabel != null) {
RowLabel.Dispose ();
RowLabel = null;
}
}
}
}

Check this sample

Apple watch: How to scroll only table contents, and not the whole watch user interface?

While the private API supports what you want to do, that feature isn't publicly available to us either in watchOS 2 or watchOS 3.

We're limited to either the entire interface scrolling (when its content is larger than the screen size), or the entire interface not scrolling at all (when its content fits within the screen size).

You may want to submit a feature request asking for a static group, sticky table row header, or scrolling region.

What comes close...

The new WKCrownSequencer and WKCrownDelegate would let you interact with a scene or specific interface object, but there's no way to override the system's gesture recognition and scroll support on behalf of the entire scrolling interface controller.

I don't think there's an elegant way to implement what you want now, that would work perfectly.

If you're determined to hack or rethink this...

If you don't want to wait for Apple to eventually offer proper support for what you want, here are a few options which might help you approach this from a different direction.

  • Try replacing the table with a picker. The picker would let you scroll through different items on the smaller screen, but it obviously won't look like a table.

  • Limit your table to a fixed number of rows which didn't exceed the screen size. You could update the row content as the crown scrolls but it would be a paging effect rather than a scrolling effect.

  • Drop down to Core Graphics to either draw the location activity indicator, or the table text to create the illusion that a portion of the screen is (not) scrolling.

  • Change the background color of table's row(s), and let the background color function as the location activity indicator.

WKInterfaceTable shows storyboard data when adding rows

I had a similar problem, which was solved by dispatching a job onto the main thread.

dispatch_async(dispatch_get_main_queue(), ^{
[self.table setNumberOfRows:[data count] withRowType:@"RowController"];
for (int i = 0; i < [data count]; i++)
{
RowController *row = [self.table rowControllerAtIndex:i];
[row bind:[data objectAtIndex:i]]; // sets labels in the row etc.
}
});

WKInterfaceTable inside WKInterfaceGroup with static BG image behind?

While I can't find the reference at the moment, an Apple employee in the developer forums has stated that having a static background image behind a scrolling table isn't possible with the current version of WatchKit.

Apple Watch: Status bar not visible after presenting a modal screen from page based navigation

This is a known issue in the final release that exhibits itself in two cases:

  1. When presenting a second modal controller (paging or single) over an existing paging modal controller
  2. When presenting a menu using Force Touch over a paging modal controller

This has been discussed in the Apple Developer Forums, and the only workaround I've heard about is one that I use in my app. Unfortunately, there's no simple code to share that solves the problem, so I'll describe the approach (which I'd consider messy, but workable).

First, you need to keep track of interface controller presentations. I have a framework for this, but you may have to roll your own. When a child interface controller has its willActivate called two times in a row (in other words, without a call to a different child interface controller) you can assume that a modal was presented/dismissed on top of it.

Your presenting/parent controller can then inform all children that the modal menu bug has happened, and those child controllers can unhide a replacement status bar with its own Cancel/Close button. With some work, you can recreate a pixel-perfect version of the standard status bar with identical behavior.

The final twist is to detect when your Watch app is suspended, then resumes. In that case, willActivate is also called twice. If you don't handle that situation, you'll end up unhiding the replacement status bar and have two on the screen simultaneously. Not a great scenario.

Getting this right is very tricky, but it does work. I just wish I had a simple code sample that you could inject.

Update: I pushed some of my workaround code to GitHub: https://github.com/mikeswanson/JBInterfaceController



Related Topics



Leave a reply



Submit