Sunday, 29 September 2013

iOS 7 UINavigationController layout issue and workaround

Before iOS 7, UINavigationController layouts navigation bar above the view to be displayed. In iOS 7, the navigation bar is overlapping with the view to be displayed. This causes display issue for certain views. One workaround is through UINavigationControllerDelegate.

// Workaround for iOS7 UINavigationController layout issue.
// In iOS7, navigation bar is overlapping with the displayed view.
// Needs to shift it down by navigation bar height and shrink its height.
// But do not do this for table view.
- (void)navigationController:(UINavigationController *)navigationController
  didShowViewController:(UIViewController *)vc
animated:(BOOL)animated {
    if(!IOS7_OR_UP)
        return;
    if ([vc.view isKindOfClass:NSClassFromString(@"UITableView")])
        return;
    
    static int barH = 0;
    if (barH == 0) {
        UIView* bar = findViewOfClass(vc.view.superview.superview.superview, NSClassFromString(@"UINavigationBar"));
        barH = bar.frame.size.height;
    }
    
    CGRect frame = vc.view.frame;
    frame.size.height -= barH;
    frame.origin.y = barH;
    vc.view.frame = frame;

}

iOS 7 UITabBarController layout issue and workaround

Before iOS 7, UITabBarController layout the tab bar below the view to be displayed. However, in iOS 7, the tab bar is overlapping with the view to be displayed. This causes some display issues for some views drawn by user.

One workaround is to shrink the size of the view to be displayed by the UITabBarController by subclass UITabBarController.

@interface MyTabBarController : UITabBarController

@end

@implementation MyTabBarController

// Workaround for iOS UITabBarController layout issue.
// In iOS7, the tab bar overlaps with the view to be displayed.
// The height of the view to be displayed with a UITabBarController needs
// to be shrinked by the height of the tab bar.
-(void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    if (!IOS7_OR_UP)
        return;
    
    static int barHeight = 0;
    if (barHeight == 0) {
        UIView* bar = findViewOfClass(self.view, NSClassFromString(@"UITabBar"));
        barHeight = bar.frame.size.height;
    }
    UIView* CV = (UIView*)self.view.subviews.firstObject;
    CV.autoresizesSubviews = YES;
    UIView* GCV = (UIView*) CV.subviews.firstObject;
    UIView* GGCV = (UIView*) GCV.subviews.firstObject;
    CGRect frame = CV.frame;
    frame.size.height = self.view.frame.size.height - barHeight;
    CV.frame = frame;
    GCV.frame = frame;
    GGCV.frame = frame;
    
}

@end

Friday, 26 July 2013

OpenGL ES: How to rotate around a specific point instead of origin?

If you want to rotate around a point (x0, y0, z0), assuming

matrix-vector multiplication order is vector * matrix,

your current modelview matrix is M1,

the rotation matrix is MR,

translation matrix from (0, 0, 0) to (x0, y0, z0) is T(x0, y0, z0),

After rotation, the modelview matrix should be

M1*T(-x0, -y0, -z0) * MR * T(x0, y0, z0)

Note if (x0, y0, z0) is in world coordinates, it needs to be first transformed to eye coordinates by

(x0, y0, z0) * M1


OpenGL ES: Is modelview matrix column major or row major?

Modelview matrix is column major. In memory, it is like

M00, M10, M20, M30, M01, M11, M21, M31, M02, M12, M22, M32, M03, M13, M23, M33

A translation of (x, y, z) is

1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1

In GLSL, matrix vector multiplication is defined as matrix * vector.

In host program, depending on how you define your matrix vector multiplication operator, it can be either matrix * vector or vector * matrix.

For a series of transformations M1, M2, M3,

if you define matrix-vector multiplication as matrix * vector,  the total transformation is

M3 * M2 * M1

If you define it as vector * matrix, the total transformation is

M1 * M2 * M3

Monday, 24 June 2013

iOS: How to Debug UIView Layout Issues

Go to https://github.com/glock45/iOS-Hierarchy-Viewer

Download and add it to your project.

When the layout issue shows up in iOS simulator, open a web browser and go to the iOS Hierarchy Viewer page (shown in app debug output at program launch.)

Starting from UIWindow, check frame of the UIViews until the problematic UIView.

Friday, 14 June 2013

CMake Configuration Failure due to Python

CMake configuration may fail due to python version issue. Sometimes a project requires an old version of python but CMake uses the newer version of python, which causes the failure. On Windows with GUI version of CMake, this can be resolved by choose the advanced option and modify the used python path to be an old version of python.

Saturday, 8 June 2013

UIKit: Stop Touches in a Subview being Handled by its Superview

If view A has a gesture recognizer, and this view has a subview B which does not have gesture recognizer, the gesture happened in the subview B will be recognized by the gesture recognizer of view A.

This may not be what you want. For example, if subview B is showing an introduction, you do not want a tap in it to be handled by view A.

One solution is to make view A a delegate of its gesture recognizer, and define a method:

-(BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
       shouldReceiveTouch:(UITouch *)touch {
    return touch.view == self;
}

In this way, the gesture recognizer will not recognize gestures happen in its subview.