Code to handle iOS horizontal and vertical screen rotation

Code to handle iOS horizontal and vertical screen rotation

1. Monitor screen rotation direction

When dealing with iOS horizontal and vertical screens, you often deal with the three enumeration types of UIDeviceOrientation, UIInterfaceOrientation, and UIInterfaceOrientationMask, which describe the screen rotation direction from different angles.

1. UIDeviceOrientation: device orientation

The iOS device orientation is obtained through the iOS accelerometer.

1) iOS defines the following seven device orientations

  1. typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
  2.  
  3. UIDeviceOrientationUnknown, // unknown orientation, possibly the device (screen) is tilted
  4.  
  5. UIDeviceOrientationPortrait, // Device (screen) upright
  6.  
  7. UIDeviceOrientationPortraitUpsideDown, // The device (screen) is upright, upside down
  8.  
  9. UIDeviceOrientationLandscapeLeft, // The device (screen) is horizontally facing left
  10.  
  11. UIDeviceOrientationLandscapeRight, // The device (screen) is horizontally facing right
  12.  
  13. UIDeviceOrientationFaceUp, // The device (screen) lies flat with its face up
  14.  
  15. UIDeviceOrientationFaceDown // The device (screen) lies flat with the face down
  16.  
  17. };

Note: UIDeviceOrientation refers to the direction of the home button, such as: the home direction is on the right, and the device (screen) direction is on the left (UIDeviceOrientationLandscapeLeft)

2) Read the device orientation

The UIDevice singleton represents the current device. From this singleton, you can get information about the device, such as the device orientation.

  1. UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

3) Listen, process, and remove notifications of device orientation changes

When the device orientation changes, a UIDeviceOrientationDidChangeNotification notification is issued; register to listen to this notification to process view display for different device orientations.

  1. // Enable and listen for device rotation notifications (if not enabled, the device orientation will always be UIInterfaceOrientationUnknown)
  2.  
  3. if (![UIDevice currentDevice].generatesDeviceOrientationNotifications) {
  4.  
  5. [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
  6.  
  7. }
  8.  
  9. [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleDeviceOrientationChange:)
  10.  
  11. name :UIDeviceOrientationDidChangeNotification object:nil];
  12.  
  13.   
  14.  
  15.   
  16.  
  17. //Handling device orientation changes
  18.  
  19. - (void)handleDeviceOrientationChange:(NSNotification *)notification{
  20.  
  21.   
  22.  
  23. UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
  24.  
  25. switch (ddeviceOrientation) {
  26.  
  27. case UIDeviceOrientationFaceUp:
  28.  
  29. NSLog(@ "Screen facing up" );
  30.  
  31. break;
  32.  
  33.   
  34.  
  35. case UIDeviceOrientationFaceDown:
  36.  
  37. NSLog(@ "Screen lying flat face down" );
  38.  
  39. break;
  40.  
  41.   
  42.  
  43. case UIDeviceOrientationUnknown:
  44.  
  45. NSLog(@ "Unknown direction" );
  46.  
  47. break;
  48.  
  49.   
  50.  
  51. case UIDeviceOrientationLandscapeLeft:
  52.  
  53. NSLog(@ "Screen is tilted horizontally to the left" );
  54.  
  55. break;
  56.  
  57.   
  58.  
  59. case UIDeviceOrientationLandscapeRight:
  60.  
  61. NSLog(@ "Screen is tilted horizontally to the right" );
  62.  
  63. break;
  64.  
  65.   
  66.  
  67. case UIDeviceOrientationPortrait:
  68.  
  69. NSLog(@ "Screen upright" );
  70.  
  71. break;
  72.  
  73.   
  74.  
  75. case UIDeviceOrientationPortraitUpsideDown:
  76.  
  77. NSLog(@ "Screen upright, upside down" );
  78.  
  79. break;
  80.  
  81.   
  82.  
  83. default :
  84.  
  85. NSLog(@ "unrecognizable" );
  86.  
  87. break;
  88.  
  89. }
  90.  
  91. }
  92.  
  93.   
  94.  
  95. //Finally, remove the notification and the notification that ends the device rotation in dealloc
  96.  
  97. - (void)dealloc{
  98.  
  99. //...
  100.  
  101. [[NSNotificationCenter defaultCenter]removeObserver:self];
  102.  
  103. [[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];

Note: After the phone is locked in portrait orientation, the UIDeviceOrientationDidChangeNotification notification becomes invalid.

2. UIInterfaceOrientation: interface orientation

The interface direction reflects the direction of the interface in iOS, which is consistent with the direction of the Home button.

1) iOS defines the following five interface directions

  1. typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
  2.  
  3. UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown, //Unknown direction
  4.  
  5. UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, //Interface upright
  6.  
  7. UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, //The interface is upright, upside down
  8.  
  9. UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, //Interface facing left
  10.  
  11. UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft //Interface faces right
  12.  
  13. } __TVOS_PROHIBITED;

Note: From the definition, we can see that the interface orientation and device orientation have a corresponding relationship, such as the vertical orientation of the interface is the vertical orientation of the device: UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown

2) Read the interface direction

UIInterfaceOrientation is related to the status bar and is obtained by calling statusBarOrientation through the UIApplication singleton

  1. UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];

3) Listen, process, and remove notifications of interface orientation changes

When the interface orientation changes, UIApplicationWillChangeStatusBarOrientationNotification and UIApplicationDidChangeStatusBarOrientationNotification notifications are issued successively; registering to listen to these two notifications can handle view display for different interface orientations.

  1. //Take monitoring UIApplicationDidChangeStatusBarOrientationNotification as an example
  2.  
  3. [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleStatusBarOrientationChange:)
  4.  
  5. name :UIApplicationDidChangeStatusBarOrientationNotification object:nil];
  6.  
  7.   
  8.  
  9.   
  10.  
  11. //Handling of interface direction changes
  12.  
  13. - (void)handleStatusBarOrientationChange: (NSNotification *)notification{
  14.  
  15.   
  16.  
  17. UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
  18.  
  19. switch (interfaceOrientation) {
  20.  
  21.   
  22.  
  23. case UIInterfaceOrientationUnknown:
  24.  
  25. NSLog(@ "Unknown direction" );
  26.  
  27. break;
  28.  
  29.   
  30.  
  31. case UIInterfaceOrientationPortrait:
  32.  
  33. NSLog(@ "Interface upright" );
  34.  
  35. break;
  36.  
  37.   
  38.  
  39. case UIInterfaceOrientationPortraitUpsideDown:
  40.  
  41. NSLog(@ "The interface is upright and upside down" );
  42.  
  43. break;
  44.  
  45.   
  46.  
  47. case UIInterfaceOrientationLandscapeLeft:
  48.  
  49. NSLog(@ "The interface faces left" );
  50.  
  51. break;
  52.  
  53.   
  54.  
  55. case UIInterfaceOrientationLandscapeRight:
  56.  
  57. NSLog(@ "The interface is facing right" );
  58.  
  59. break;
  60.  
  61.   
  62.  
  63. default :
  64.  
  65. break;
  66.  
  67. }
  68.  
  69. }
  70.  
  71.   
  72.  
  73. //Finally remove the notification in dealloc
  74.  
  75. - (void)dealloc{
  76.  
  77. //...
  78.  
  79. [[NSNotificationCenter defaultCenter]removeObserver:self];
  80.  
  81. [[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];
  82.  
  83. }

Note: After the phone is locked in portrait orientation, the UIApplicationWillChangeStatusBarOrientationNotification and UIApplicationDidChangeStatusBarOrientationNotification notifications are also invalid.

3.UIInterfaceOrientationMask

UIInterfaceOrientationMask is a type defined to integrate multiple UIInterfaceOrientation, related to ViewController, there are 7 types in total

1) UIInterfaceOrientationMask definition in iOS

  1. typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
  2.  
  3. UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
  4.  
  5. UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
  6.  
  7. UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
  8.  
  9. UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
  10.  
  11. UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
  12.  
  13. UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
  14.  
  15. UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
  16.  
  17. } __TVOS_PROHIBITED;

2) Use of UIInterfaceOrientationMask

In ViewController, you can override the return type of the -(UIInterfaceOrientationMask)supportedInterfaceOrientations method to determine which interface directions the UIViewController can support.

  1. //Support interface upright
  2.  
  3. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  4.  
  5. return UIInterfaceOrientationMaskPortrait;
  6.  
  7. }

Summary: UIDeviceOrientation (device orientation) and UIInterfaceOrientation (screen orientation) are two different concepts. The former represents a state of the device, while the latter is the response of the screen on the user interface in response to different device states. When an iOS device is rotated, the rotation event is received by UIKit, and then the UIWindow object of the current program is notified through AppDelegate. The UIWindow object notifies its rootViewController. If the rootViewController supports the rotated screen orientation, the rotation is completed, otherwise it is not rotated; the same is true for the pop-up ViewController.

2. Setting the rotation direction in the view controller

0. About disabling horizontal screen operation (not recommended)

There are two more conventional methods.

Method 1: In the project's General–>Deployment Info–>Device Orientation, only check Portrait.

Check Portrait.png

Method 2: Device Orientation default settings, implement supportedInterfaceOrientationsForWindow: in AppDelegate and only return UIInterfaceOrientationMaskPortraitt (vertical screen)

  1. - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
  2.  
  3. return UIInterfaceOrientationMaskPortrait;
  4.  
  5. }

Note: Very few apps have all interfaces in portrait mode, because there are always interfaces that need to support landscape mode, such as video playback pages. Therefore, it is not recommended to prohibit the app pages from being in landscape mode.

Here's how to set the rotation direction in the view controller in your project:

1. APP supports multiple directions

APP supports multiple directions.png

Note: In this way, the APP supports both landscape and portrait orientations, but the page orientations supported by the specific view controller need further processing. Since portrait orientation (Upside Down) is not supported, even if the device is upside down, the device and screen orientation will not be obtained through the API.

2. Support ViewController screen orientation setting

1) Key functions

The interface directions supported by the view controller are mainly controlled by the following three functions

  1. //Whether to rotate automatically, return YES to enable automatic rotation, return NO to disable rotation
  2.  
  3. - (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
  4.  
  5.   
  6.  
  7. // Return the supported directions
  8.  
  9. - (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
  10.  
  11.   
  12.  
  13. //The view controller launched modally prioritizes the supported screen direction
  14.  
  15. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;

2) QSBaseViewController settings

  1. //QSBaseViewController.h
  2.  
  3. @interface QSBaseController: UIViewController
  4.  
  5.   
  6.  
  7. @ end  
  8.  
  9.   
  10.  
  11. //QSBaseViewController.m
  12.  
  13. @implementation QSBaseController
  14.  
  15.   
  16.  
  17. //#pragma mark - control screen rotation method
  18.  
  19. //Whether to rotate automatically, return YES to enable automatic rotation, return NO to disable rotation
  20.  
  21. - (BOOL)shouldAutorotate{
  22.  
  23. return   NO ;
  24.  
  25. }
  26.  
  27.   
  28.  
  29. // Return the supported directions
  30.  
  31. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  32.  
  33. return UIInterfaceOrientationMaskPortrait;
  34.  
  35. }
  36.  
  37.   
  38.  
  39. //The view controller launched modally prioritizes the supported screen direction
  40.  
  41. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
  42.  
  43. return UIInterfaceOrientationPortrait;
  44.  
  45. }
  46.  
  47. @ end  

Note 1: QSBaseViewController does not support rotation by default and only supports the vertical orientation of the interface. All Controllers in the project inherit from QSBaseViewController. You can override these three methods to allow the Controller to support orientations or rotations other than vertical.

3) Set in QSNavigationController

Goal: When pushing a view controller through QSNavigationController, set the screen rotation support to the view controller that is pushed most recently ([self.viewControllers lastObject]).

  1. //QSNavigationController.h
  2.  
  3. @interface QSNavigationController : UINavigationController
  4.  
  5.   
  6.  
  7. @ end  
  8.  
  9.   
  10.  
  11. //QSNavigationController.m
  12.  
  13. @implementation QSNavigationController
  14.  
  15.   
  16.  
  17. #pragma mark - Control screen rotation method
  18.  
  19. - (BOOL)shouldAutorotate{
  20.  
  21. return [[self.viewControllers lastObject]shouldAutorotate];
  22.  
  23. }
  24.  
  25.   
  26.  
  27. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  28.  
  29. return [[self.viewControllers lastObject]supportedInterfaceOrientations];
  30.  
  31. }
  32.  
  33.   
  34.  
  35. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
  36.  
  37. return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
  38.  
  39. }
  40.  
  41. @ end  

4) Set in QSTabBarController

Goal: TabBarController is usually used as the rootViewController of the entire program. Each Tab displayed on UITabBar corresponds to a ViewController. Every time a Tab is clicked, the ViewController (self.selectedViewController) that appears controls the screen rotation and supported directions.

  1. //QSTabBarController.h
  2.  
  3. @interface QSTabBarController : UITabBarController
  4.  
  5.   
  6.  
  7. @ end  
  8.  
  9.   
  10.  
  11. //QSTabBarController.m
  12.  
  13. @implementation QSTabBarController
  14.  
  15.   
  16.  
  17. #pragma mark - Control screen rotation method
  18.  
  19. - (BOOL)shouldAutorotate{
  20.  
  21. return [self.selectedViewController shouldAutorotate];
  22.  
  23. }
  24.  
  25.   
  26.  
  27. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  28.  
  29. return [self.selectedViewController supportedInterfaceOrientations];
  30.  
  31. }
  32.  
  33.   
  34.  
  35. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
  36.  
  37. return [self.selectedViewController preferredInterfaceOrientationForPresentation];
  38.  
  39. }
  40.  
  41. @ end  

3. View processing under screen rotation direction

1. When the screen rotates, it is recommended to listen to UIApplicationDidChangeStatusBarOrientationNotification

Reason 1: The supportedInterfaceOrientations method ultimately returns multiple interface orientations.

Reason 2 (the most important reason): What we really need to deal with is the change of UI when the page direction rotates. When the physical direction of the device rotates, if the page of the current controller does not rotate at this time, we may have problems when changing the UI layout.

2. Screen width and height processing

1) After iOS 8, when the screen is rotated, [[UIScreen mainScreen] bounds] also changes. For example, the screen width in landscape mode is actually the screen height in portrait mode.

2) When we process the view layout, if we use the width and height of the screen, do not use SCREEN_HEIGHT and SCREEN_WIDTH directly, but use SCREEN_MIN and SCREEN_MAX

  1. #define SCREEN_HEIGHT CGRectGetHeight([[UIScreen mainScreen] bounds])
  2.  
  3. #define SCREEN_WIDTH CGRectGetWidth([[UIScreen mainScreen] bounds])
  4.  
  5.   
  6.  
  7. #define SCREEN_MIN MIN (SCREEN_HEIGHT,SCREEN_WIDTH)
  8.  
  9. #define SCREEN_MAX MAX (SCREEN_HEIGHT,SCREEN_WIDTH)

Note: When the screen is in portrait mode, the width is SCREEN_MIN and the height is SCREEN_MAX; when the screen is in landscape mode, the width is SCREEN_MAX and the height is SCREEN_MIN.

3. Processing Demo under screen rotation

  1. //Monitoring UIApplicationDidChangeStatusBarOrientationNotification processing
  2.  
  3. - (void)handleStatusBarOrientationChange: (NSNotification *)notification{
  4.  
  5.   
  6.  
  7. UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
  8.  
  9. BOOL isLandscape = NO ;
  10.  
  11. switch (interfaceOrientation) {
  12.  
  13.   
  14.  
  15. case UIInterfaceOrientationUnknown:
  16.  
  17. NSLog(@ "Unknown direction" );
  18.  
  19. break;
  20.  
  21.   
  22.  
  23. case UIInterfaceOrientationPortrait:
  24.  
  25. case UIInterfaceOrientationPortraitUpsideDown:
  26.  
  27. isLandscape = NO ;
  28.  
  29. break;
  30.  
  31.   
  32.  
  33. case UIInterfaceOrientationLandscapeLeft:
  34.  
  35. case UIInterfaceOrientationLandscapeRight:
  36.  
  37. isLandscape = YES;
  38.  
  39. break;
  40.  
  41.   
  42.  
  43. default :
  44.  
  45. break;
  46.  
  47. }
  48.  
  49. if (isLandscape) {
  50.  
  51. self.tableView.frame = CGRectMake(0, 0, SCREEN_MAX, SCREEN_MIN - 44);
  52.  
  53. } else {
  54.  
  55. self.tableView.frame = CGRectMake(0, 0, SCREEN_MIN, SCREEN_MAX - 64);
  56.  
  57. }
  58.  
  59.   
  60.  
  61. [self.tableView reloadData];
  62.  
  63. }

Note: Of course, you can also choose to use an excellent AutoLayout layout third-party library such as Masonry to handle it, and storyBoard is the second best choice for layout.

4. Processing Demo effect diagram under screen rotation

Vertical screen effect.png

Horizontal screen effect.png

5. Suggestions for screen rotation

1) Before and after rotation, the current display position of the view should remain unchanged as much as possible

2) Response to temporary interface operations during rotation

3) If there is a tableview in the view, after rotation, force [tableview reloadData] to ensure that the new row can fill the full screen after the direction changes.

4. Force horizontal screen

Some pages in the app, such as the video playback page, require horizontal screen as soon as they appear. These horizontal screen pages are either modally popped up or pushed in.

1. Setting the forced horizontal screen when the ViewController pops up modally

  1. //QSShow3Controller.m
  2.  
  3. - (BOOL)shouldAutorotate{
  4.  
  5. return   NO ;
  6.  
  7. }
  8.  
  9.   
  10.  
  11. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  12.  
  13. return UIInterfaceOrientationMaskLandscapeRight;
  14.  
  15. }
  16.  
  17.   
  18.  
  19. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
  20.  
  21. return UIInterfaceOrientationLandscapeRight;
  22.  
  23. }
  24.  
  25.   
  26.  
  27. // Modal popup
  28.  
  29. QSShow3Controller *vc = [[QSShow3Controller alloc]init];
  30.  
  31. [self presentViewController:vc animated:YES completion:nil];

Note: This situation is relatively simple to handle.

2. Setting the forced horizontal screen when pushing ViewController

  1. //QSShow4Controller.m
  2.  
  3. -(void)viewWillAppear:(BOOL)animated{
  4.  
  5.   
  6.  
  7. [super viewWillAppear:animated];
  8.  
  9. [self setInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
  10.  
  11. }
  12.  
  13.   
  14.  
  15. //Force screen rotation (this method is best placed in BaseVController)
  16.  
  17. - (void)setInterfaceOrientation:(UIInterfaceOrientation)orientation{
  18.  
  19.   
  20.  
  21. if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
  22.  
  23. SEL selector = NSSelectorFromString(@ "setOrientation:" );
  24.  
  25. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
  26.  
  27. [invocation setSelector:selector];
  28.  
  29. [invocation setTarget:[UIDevice currentDevice]];
  30.  
  31. // Start from 2 because the first two parameters are already occupied by selector and target
  32.  
  33. [invocation setArgument:&orientation atIndex:2];
  34.  
  35. [invocation invoke];
  36.  
  37. }
  38.  
  39. }
  40.  
  41.   
  42.  
  43. //Must return YES
  44.  
  45. - (BOOL)shouldAutorotate{
  46.  
  47. return YES;
  48.  
  49. }
  50.  
  51.   
  52.  
  53. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  54.  
  55. return UIInterfaceOrientationMaskLandscapeRight;
  56.  
  57. }
  58.  
  59.   
  60.  
  61. //Push
  62.  
  63. QSShow4Controller *vc = [[QSShow4Controller alloc]init];
  64.  
  65. [self.navigationController pushViewController:vc animated:YES];

Note: Apple does not allow direct calls to the setOrientation method, otherwise there is a risk of being rejected; using the NSInvocation object to send a message to [UIDevice currentDevice] to force a change in the device orientation so that the page orientation changes accordingly is allowed by Apple.

V. Others

1. When the APP is started, the home page UI (this page only supports vertical screen) is wrong in the horizontal screen of the mobile phone (added by 2017/6/20)

  1. //Set the status bar to vertical screen
  2.  
  3. [[UIApplication sharedApplication]setStatusBarOrientation:UIInterfaceOrientationPortrait];

For the above detailed source code, please refer to: QSRotationScreenDemo

https://github.com/buaa0300/QSKitDemo/tree/master/QSRotationScreenDemo

<<:  Android Complete Componentization Solution Practice

>>:  A Brief Discussion on iOS Crash (Part 2)

Recommend

Analysis of member activity promotion techniques!

This article once again focuses on a membership a...

Double No. 1! Perfect ending! This time we really have to say goodbye...

Screenshot from the Beijing Winter Paralympic Gam...

Google Glass will stop taking orders and move from Google X to a new division

Google said it will stop taking orders for Google ...

iPhone 7 Launch Guide: Get it first

Apple has scheduled the much-anticipated iPhone 7 ...

10 Tips for Solving Problems in Android Development

[51CTO.com original article] There are three comm...

Tips for K12 & Preschool Education Advertising!

As homogeneous competition in the industry become...

Are the “edited” vegetables delicious?

The cover image is a copyrighted image. Reprintin...

The ballpoint pen you use every day actually has so much knowledge

Many people don’t know that ordinary-looking stat...