├── .gitignore ├── EmojiLayout.plist ├── Makefile ├── PSEmojiLayout+KBResize.m ├── PSEmojiLayout+Layout.m ├── PSEmojiLayout.h ├── README.md ├── Tweak.xm ├── control └── layout └── Library └── PreferenceLoader └── Preferences └── EmojiLayout ├── EmojiLayout.plist ├── EmojiLayout.png ├── EmojiLayout@2x.png └── EmojiLayout@3x.png /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | packages 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /EmojiLayout.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Bundles 8 | 9 | com.apple.UIKit 10 | 11 | CoreFoundationVersion 12 | 13 | 793 14 | 1144.17 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE_VERSION = 1.2.0 2 | 3 | ifeq ($(SIMULATOR),1) 4 | TARGET = simulator:clang:latest:8.0 5 | ARCHS = x86_64 i386 6 | else 7 | TARGET = iphone:clang:latest:6.0 8 | ARCHS = armv7 arm64 9 | endif 10 | 11 | include $(THEOS)/makefiles/common.mk 12 | 13 | LIBRARY_NAME = EmojiLayout 14 | $(LIBRARY_NAME)_FILES = PSEmojiLayout+Layout.m PSEmojiLayout+KBResize.m Tweak.xm 15 | $(LIBRARY_NAME)_CFLAGS = -fobjc-arc 16 | $(LIBRARY_NAME)_INSTALL_PATH = /Library/MobileSubstrate/DynamicLibraries/EmojiPort 17 | $(LIBRARY_NAME)_EXTRA_FRAMEWORKS = CydiaSubstrate 18 | $(LIBRARY_NAME)_USE_SUBSTRATE = 1 19 | 20 | include $(THEOS_MAKE_PATH)/library.mk 21 | include ../../preferenceloader-sim/locatesim.mk 22 | 23 | ifeq ($(SIMULATOR),1) 24 | setup:: clean all 25 | @rm -f /opt/simject/$(LIBRARY_NAME).dylib 26 | @cp -v $(THEOS_OBJ_DIR)/$(LIBRARY_NAME).dylib /opt/simject 27 | @cp -v $(PWD)/$(LIBRARY_NAME).plist /opt/simject 28 | @sudo mkdir -p $(PL_SIMULATOR_PLISTS_PATH) 29 | @sudo cp -vR $(PWD)/EmojiLayout $(PL_SIMULATOR_PLISTS_PATH)/ 30 | endif 31 | -------------------------------------------------------------------------------- /PSEmojiLayout+KBResize.m: -------------------------------------------------------------------------------- 1 | #import "PSEmojiLayout.h" 2 | #import 3 | #import 4 | 5 | @implementation PSEmojiLayout (KBResize) 6 | 7 | + (CGFloat)getHeight:(NSString *)name chocoL:(CGFloat)chocoL chocoP:(CGFloat)chocoP truffleL:(CGFloat)truffleL truffleP:(CGFloat)truffleP l:(CGFloat)l p:(CGFloat)p padL:(CGFloat)padL padP:(CGFloat)padP { 8 | CGFloat height = 0.0; 9 | BOOL isLandscape = [name rangeOfString:@"Landscape"].location != NSNotFound 10 | || [name rangeOfString:@"Caymen"].location != NSNotFound 11 | || (!IS_IOS_OR_NEWER(iOS_7_0) && ( 12 | [name rangeOfString:@"3587139855"].location != NSNotFound 13 | || [name rangeOfString:@"203519438"].location != NSNotFound)); 14 | if ([name rangeOfString:@"Choco"].location != NSNotFound) { 15 | // iPhone 6 16 | height = isLandscape ? chocoL : chocoP; 17 | } else if ([name rangeOfString:@"Truffle"].location != NSNotFound) { 18 | // iPhone 6+ 19 | height = isLandscape ? truffleL : truffleP; 20 | } else { 21 | // 3.5, 4-inches iDevices or iPad 22 | if (IS_IPAD) 23 | height = isLandscape ? padL : padP; 24 | else 25 | height = isLandscape ? l : p; 26 | } 27 | return height; 28 | } 29 | 30 | + (CGFloat)barHeight:(NSString *)name { 31 | return [self getHeight:name chocoL:37.0 chocoP:47.0 truffleL:40.0 truffleP:50.0 l:32.0 p:40.0 padL:56.0 padP:56.0]; 32 | } 33 | 34 | + (CGFloat)keyboardHeight:(NSString *)name { 35 | return [self getHeight:name chocoL:194.0 chocoP:258.0 truffleL:194.0 truffleP:271.0 l:162.0 p:253.0 padL:398.0 padP:313.0]; 36 | } 37 | 38 | + (CGFloat)scrollViewHeight:(NSString *)name { 39 | return [self keyboardHeight:name] - [self barHeight:name]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /PSEmojiLayout+Layout.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "PSEmojiLayout.h" 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | 10 | @implementation PSEmojiLayout 11 | 12 | + (BOOL)isPortrait { 13 | NSInteger orientation = [UIKeyboardImpl.activeInstance interfaceOrientation]; 14 | return orientation == 1 || orientation == 2; 15 | } 16 | 17 | + (UIKeyboardEmojiScrollView *)emojiScrollView { 18 | return (UIKeyboardEmojiScrollView *)[NSClassFromString(@"UIKeyboardEmojiInputController") activeInputView]; 19 | } 20 | 21 | + (NSInteger)rowCount:(BOOL)portrait { 22 | return [NSClassFromString(@"UIKeyboardEmojiGraphics") rowCount:portrait]; 23 | } 24 | 25 | + (NSInteger)colCount:(BOOL)portrait { 26 | return [NSClassFromString(@"UIKeyboardEmojiGraphics") colCount:portrait]; 27 | } 28 | 29 | + (CGSize)emojiSize:(BOOL)portrait { 30 | return [NSClassFromString(@"UIKeyboardEmojiGraphics") emojiSize:portrait]; 31 | } 32 | 33 | + (CGPoint)margin:(BOOL)portrait { 34 | return CGPointMake(IS_IPAD ? (portrait ? MARGIN_IPAD_PORTRAIT : MARGIN_IPAD) : MARGIN, [self dotHeight]); 35 | } 36 | 37 | + (CGFloat)marginBottom:(BOOL)portrait { 38 | return IS_IPAD ? (portrait ? MARGIN_BOTTOM_IPAD_PORTRAIT : MARGIN_BOTTOM_IPAD) : MARGIN_BOTTOM; 39 | } 40 | 41 | + (CGFloat)offset:(BOOL)portrait { 42 | return IS_IOS_OR_NEWER(iOS_7_0) ? [NSClassFromString(@"UIKeyboardEmojiGraphics") emojiPageControlYOffset:portrait] : DEFAULT_OFFSET; 43 | } 44 | 45 | + (CGFloat)dotHeight { 46 | CGFloat height = 0.0; 47 | UIKeyboardEmojiScrollView *scrollView = [self emojiScrollView]; 48 | if (scrollView) { 49 | _UIEmojiPageControl *pageControl = (_UIEmojiPageControl *)[scrollView valueForKey:@"_pageControl"]; 50 | height = pageControl ? pageControl.frame.size.height : [pageControl _pageIndicatorImage].size.height; 51 | } 52 | return height == 0.0 ? DOT_HEIGHT : height; 53 | } 54 | 55 | + (CGFloat)_screenWidth { 56 | CGSize screenSize = UIScreen.mainScreen.bounds.size; 57 | return MIN(screenSize.width, screenSize.height); 58 | } 59 | 60 | + (CGFloat)_scrollViewHeight:(BOOL)portrait { 61 | NSString *type = portrait ? @"" : @"Landscape"; 62 | if (!IS_IPAD) { 63 | CGFloat screenWidth = [self _screenWidth]; 64 | if (screenWidth >= 414.0) 65 | type = [type stringByAppendingString:@"Truffle"]; 66 | else if (screenWidth >= 375.0) 67 | type = [type stringByAppendingString:@"Choco"]; 68 | } 69 | return [self scrollViewHeight:type]; 70 | } 71 | 72 | + (CGFloat)keyboardWidth:(BOOL)portrait { 73 | if (IS_IOS_OR_NEWER(iOS_8_0)) 74 | return [[NSClassFromString(@"UIPeripheralHost") sharedInstance] transformedContainerView].bounds.size.width; 75 | CGRect screenRect = UIScreen.mainScreen.bounds; 76 | return portrait ? screenRect.size.width : screenRect.size.height; 77 | } 78 | 79 | + (NSInteger)bestRowForLandscape { 80 | return IS_IPAD ? BEST_ROW_IPAD : BEST_ROW; 81 | } 82 | 83 | + (NSInteger)bestColForLandscape { 84 | if (IS_IPAD) 85 | return BEST_COL_IPAD; 86 | CGFloat w = [self keyboardWidth:NO]; 87 | if (w >= 736.0) 88 | return BEST_COL_6S; 89 | if (w >= 568.0) 90 | return BEST_COL_NON4S; 91 | return BEST_COL; 92 | } 93 | 94 | + (CGFloat)paddingX:(BOOL)portrait { 95 | CGFloat w = [self keyboardWidth:portrait]; 96 | NSInteger col = [self colCount:portrait]; 97 | CGFloat padding = (w - (2 * [self margin:portrait].x) - (col * [self emojiSize:portrait].width)) / (col - 1); 98 | return padding; 99 | } 100 | 101 | + (CGFloat)paddingY:(BOOL)portrait { 102 | CGFloat h = [self _scrollViewHeight:portrait]; 103 | NSInteger row = [self rowCount:portrait]; 104 | CGFloat padding = (h - [self margin:portrait].y - [self offset:portrait] - [self marginBottom:portrait] - (row * [self emojiSize:portrait].height)) / (row - 1); 105 | return padding; 106 | } 107 | 108 | + (CGPoint)padding:(BOOL)portrait { 109 | return CGPointMake([self paddingX:portrait], [self paddingY:portrait]); 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /PSEmojiLayout.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "../../PSPrefs/PSPrefs.x" 3 | 4 | #define DEFAULT_OFFSET 6.0 5 | #define MARGIN 8.5 6 | #define MARGIN_IPAD 10.0 7 | #define MARGIN_IPAD_PORTRAIT 12.0 8 | #define MARGIN_BOTTOM 6.0 9 | #define MARGIN_BOTTOM_IPAD 10.0 10 | #define MARGIN_BOTTOM_IPAD_PORTRAIT 14.0 11 | #define DOT_HEIGHT 14.0 12 | 13 | #define BEST_ROW_IPAD 5 14 | #define BEST_ROW 3 15 | #define BEST_COL_IPAD 16 16 | #define BEST_COL_6S 15 17 | #define BEST_COL_NON4S 14 18 | #define BEST_COL 12 19 | 20 | @interface PSEmojiLayout : NSObject 21 | @end 22 | 23 | @interface PSEmojiLayout (Layout) 24 | + (BOOL)isPortrait; 25 | + (UIKeyboardEmojiScrollView *)emojiScrollView; 26 | + (CGSize)emojiSize:(BOOL)portrait; 27 | + (CGPoint)margin:(BOOL)portrait; 28 | + (CGPoint)padding:(BOOL)portrait; 29 | + (CGFloat)paddingX:(BOOL)portrait; 30 | + (CGFloat)paddingY:(BOOL)portrait; 31 | + (CGFloat)offset:(BOOL)portrait; 32 | + (CGFloat)marginBottom:(BOOL)portrait; 33 | + (CGFloat)dotHeight; 34 | + (CGFloat)keyboardWidth:(BOOL)portrait; 35 | + (NSInteger)rowCount:(BOOL)portrait; 36 | + (NSInteger)colCount:(BOOL)portrait; 37 | + (NSInteger)bestRowForLandscape; 38 | + (NSInteger)bestColForLandscape; 39 | @end 40 | 41 | @interface PSEmojiLayout (KBResize) 42 | + (CGFloat)getHeight:(NSString *)name chocoL:(CGFloat)chocoL chocoP:(CGFloat)chocoP truffleL:(CGFloat)truffleL truffleP:(CGFloat)truffleP l:(CGFloat)l p:(CGFloat)p padL:(CGFloat)padL padP:(CGFloat)padP; 43 | + (CGFloat)barHeight:(NSString *)name; 44 | + (CGFloat)keyboardHeight:(NSString *)name; 45 | + (CGFloat)scrollViewHeight:(NSString *)name; 46 | @end 47 | 48 | #define SoftPSEmojiLayout NSClassFromString(@"PSEmojiLayout") 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EmojiLayout 2 | ============= 3 | 4 | Adjust rows and columns number of emoji page. 5 | 6 | Purpose 7 | ========== 8 | 9 | To mimic iOS 8.3+ emoji keyboard style. 10 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "../../PSPrefs/PSPrefs.x" 4 | #import "PSEmojiLayout.h" 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | 12 | NSInteger row, col; 13 | 14 | %hook UIKeyboardEmojiGraphics 15 | 16 | + (NSInteger)rowCount:(BOOL)portrait { 17 | return portrait ? row : [PSEmojiLayout bestRowForLandscape]; 18 | } 19 | 20 | + (NSInteger)colCount:(BOOL)portrait { 21 | return portrait ? col : [PSEmojiLayout bestColForLandscape]; 22 | } 23 | 24 | + (CGPoint)padding:(BOOL)portrait { 25 | return [PSEmojiLayout padding:portrait]; 26 | } 27 | 28 | + (CGPoint)margin:(BOOL)portrait { 29 | return [PSEmojiLayout margin:portrait]; 30 | } 31 | 32 | %end 33 | 34 | BOOL pageZero = NO; 35 | 36 | %hook UIKeyboardEmojiPage 37 | 38 | - (void)setEmoji:(NSArray *)emoji { 39 | BOOL portrait = NO; 40 | if (!pageZero && emoji.count && ((portrait = [PSEmojiLayout isPortrait]) || IS_IPAD)) { 41 | NSInteger Row = [%c(UIKeyboardEmojiGraphics) rowCount:portrait]; 42 | NSInteger Col = [%c(UIKeyboardEmojiGraphics) colCount:portrait]; 43 | NSInteger Page = Row * Col; 44 | NSMutableArray *reorderedEmoji = [NSMutableArray arrayWithCapacity:Page]; 45 | UIKeyboardEmoji *emptyEmoji = [SoftPSEmojiUtilities emojiWithString:@""]; 46 | for (NSInteger i = 0; i < Page; ++i) { 47 | NSInteger emojiIndex = ((i % Col) * Row) + (i / Col); 48 | [reorderedEmoji addObject:emojiIndex < emoji.count ? [emoji objectAtIndex:emojiIndex] : emptyEmoji]; 49 | } 50 | if (reorderedEmoji.count) { 51 | %orig(reorderedEmoji); 52 | return; 53 | } 54 | } 55 | %orig; 56 | } 57 | 58 | - (UIKeyboardEmojiView *)closestForPoint:(CGPoint)point { 59 | UIKeyboardEmojiView *orig = %orig; 60 | return orig.emoji.emojiString.length == 0 ? nil : orig; 61 | } 62 | 63 | %end 64 | 65 | %hook UIKeyboardEmojiScrollView 66 | 67 | - (void)layoutRecents { 68 | pageZero = YES; 69 | %orig; 70 | pageZero = NO; 71 | } 72 | 73 | - (void)layoutPages { 74 | if (MSHookIvar(self, "_currentPage") >= MSHookIvar(self, "_pages").count) 75 | MSHookIvar(self, "_currentPage") = 0; 76 | %orig; 77 | } 78 | 79 | %end 80 | 81 | %group iOS6Up 82 | 83 | %hook UIKeyboardEmojiInputController 84 | 85 | - (void)emojiUsed:(UIKeyboardEmoji *)emoji { 86 | NSString *emojiString = emoji.emojiString; 87 | if (!emojiString || [emojiString isEqualToString:@""]) 88 | return; 89 | if ([emoji respondsToSelector:@selector(hasDingbat)] && [emoji hasDingbat]) 90 | emojiString = [NSString stringWithFormat:@"%@%@", emojiString, FE0F]; 91 | __block __weak UIKeyboardImpl *kbImpl = [UIKeyboardImpl sharedInstance]; 92 | if ([kbImpl acceptInputString:emojiString]) { 93 | if (IS_IOS_OR_NEWER(iOS_7_0)) { 94 | [kbImpl.taskQueue addTask:^{ 95 | [kbImpl addInputString:emojiString withFlags:0 executionContext:kbImpl.taskQueue.executionContext]; 96 | }]; 97 | } else 98 | [kbImpl addInputString:emojiString fromVariantKey:0]; 99 | } 100 | #define usageHistory MSHookIvar(self, "_usageHistory") 101 | UIKeyboardEmojiDefaultsController *emojiDefaultsController = [%c(UIKeyboardEmojiDefaultsController) sharedController]; 102 | if (usageHistory == nil) { 103 | id usageHistoryKey = emojiDefaultsController.usageHistoryKey; 104 | if (usageHistoryKey) 105 | usageHistory = (__bridge NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFPropertyListRef)usageHistoryKey, kCFPropertyListMutableContainersAndLeaves); 106 | else 107 | usageHistory = [[NSMutableDictionary alloc] initWithCapacity:10]; 108 | } 109 | #define recents MSHookIvar(self, "_recents") 110 | if (recents == nil) { 111 | id recentsKey = emojiDefaultsController.recentsKey; 112 | if (recentsKey) 113 | recents = (__bridge NSMutableArray *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFPropertyListRef)recentsKey, kCFPropertyListMutableContainersAndLeaves); 114 | else 115 | recents = [[NSMutableArray alloc] initWithCapacity:10]; 116 | } 117 | #define currentSequence MSHookIvar(self, "_currentSequence") 118 | emojiDefaultsController.currentSequenceKey = currentSequence; 119 | NSNumber *sequence_num = [NSNumber numberWithInt:currentSequence++]; 120 | NSString *emojiString2 = emoji.emojiString; 121 | NSMutableArray *emojiInHistory = usageHistory[emojiString2]; 122 | if (emojiInHistory == nil) 123 | emojiInHistory = [NSMutableArray arrayWithCapacity:0]; 124 | [emojiInHistory addObject:sequence_num]; 125 | [usageHistory setObject:emojiInHistory forKey:emojiString2]; 126 | emojiDefaultsController.usageHistoryKey = usageHistory; 127 | double scoreForEmoji = [self scoreForEmoji:emoji]; 128 | NSUInteger recentsCount = recents.count; 129 | NSUInteger maxCount = [%c(UIKeyboardEmojiGraphics) rowCount:YES] * [%c(UIKeyboardEmojiGraphics) colCount:YES]; 130 | NSUInteger indexOfEmojiToBeRemoved = [recents indexOfObject:emoji]; 131 | if (recentsCount && indexOfEmojiToBeRemoved != NSNotFound) 132 | [recents removeObjectAtIndex:indexOfEmojiToBeRemoved]; 133 | else if (recentsCount > maxCount) { 134 | UIKeyboardEmoji *lastRecentEmoji = [recents lastObject]; 135 | double scoreOfLastRecentEmoji = [self scoreForEmoji:lastRecentEmoji]; 136 | if (scoreForEmoji > scoreOfLastRecentEmoji) 137 | [recents removeLastObject]; 138 | } 139 | NSUInteger idx = 0; 140 | if (recentsCount) { 141 | do { 142 | UIKeyboardEmoji *emojiAtIndex = recents[idx]; 143 | double scoreOfEmojiAtIndex = [self scoreForEmoji:emojiAtIndex]; 144 | if (scoreForEmoji > scoreOfEmojiAtIndex) 145 | break; 146 | } while (++idx != recentsCount); 147 | } 148 | [recents insertObject:emoji atIndex:idx]; 149 | emojiDefaultsController.recentsKey = recents; 150 | ((UIKeyboardEmojiCategory *)[%c(UIKeyboardEmojiCategory) categoryForType:0]).emoji = recents; 151 | } 152 | 153 | %end 154 | 155 | %end 156 | 157 | %group iOS7Up 158 | 159 | %hook _UIEmojiPageControl 160 | 161 | - (void)layoutSubviews { 162 | self.hidesForSinglePage = NO; 163 | %orig; 164 | } 165 | 166 | %end 167 | 168 | %hook UIKeyboardEmojiCategory 169 | 170 | + (NSUInteger)hasVariantsForEmoji:(NSString *)emoji { 171 | if (!emoji || [emoji isEqualToString:@""]) 172 | return NO; 173 | return %orig; 174 | } 175 | 176 | %end 177 | 178 | %end 179 | 180 | #if !__LP64__ 181 | 182 | %group iOS56 183 | 184 | %hook EmojiPageControl 185 | 186 | - (void)layoutSubviews { 187 | self.hidesForSinglePage = NO; 188 | %orig; 189 | } 190 | 191 | %end 192 | 193 | BOOL draw = NO; 194 | 195 | %hook UIKeyboardEmojiPage 196 | 197 | - (void)drawRect:(CGRect)rect { 198 | draw = YES; 199 | %orig; 200 | draw = NO; 201 | } 202 | 203 | %end 204 | 205 | %end 206 | 207 | %group iOS6 208 | 209 | %hookf(void, CTFontDrawGlyphs, CTFontRef font, const CGGlyph glyphs[], const CGPoint positions[], size_t count, CGContextRef context) { 210 | if (draw && glyphs[0] == 0) 211 | return; 212 | %orig; 213 | } 214 | 215 | %end 216 | 217 | #endif 218 | 219 | static const NSString *tweakIdentifier = @"com.PS.EmojiLayout"; 220 | static const NSString *colKey = @"columns"; 221 | static const NSString *rowKey = @"rows"; 222 | 223 | HaveCallback() { 224 | GetPrefs(); 225 | GetInt2(col, IS_IPAD ? 12 : 8); 226 | GetInt2(row, IS_IPAD ? 3 : 5); 227 | } 228 | 229 | %ctor { 230 | HaveObserver(); 231 | callback(); 232 | dlopen(realPath2(@"/usr/lib/libEmojiLibrary.dylib"), RTLD_NOW); 233 | if (IS_IOS_OR_NEWER(iOS_6_0)) { 234 | %init(iOS6Up); 235 | } 236 | if (IS_IOS_OR_NEWER(iOS_7_0)) { 237 | %init(iOS7Up); 238 | } 239 | #if !__LP64__ 240 | else { 241 | %init(iOS56); 242 | if (IS_IOS_BETWEEN(iOS_6_0, iOS_6_1)) { 243 | %init(iOS6); 244 | } 245 | } 246 | #endif 247 | %init; 248 | } 249 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.ps.emojilayout 2 | Name: EmojiLayout 3 | Depends: preferenceloader, firmware (>= 6.0), firmware (<< 8.3) 4 | Version: 1.0.0 5 | Architecture: iphoneos-arm 6 | Description: Layout the emoji keyboard. 7 | Maintainer: PoomSmart 8 | Author: PoomSmart 9 | Section: Tweaks 10 | Depiction: https://poomsmart.github.io/repo/depictions/emojilayout.html 11 | Tag: compatible::ios6, compatible::ios7, compatible::ios8 12 | -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | title 6 | EmojiLayout 7 | entry 8 | 9 | cell 10 | PSLinkCell 11 | icon 12 | EmojiLayout.png 13 | label 14 | EmojiLayout 15 | 16 | items 17 | 18 | 19 | cell 20 | PSGroupCell 21 | label 22 | Layout 23 | footerAlignment 24 | 1 25 | footerText 26 | iPhone (3.5/4-inches) default: (row: 5, col: 8) 27 | iPhone 6 Plus default: (row: 5, col: 9) 28 | iPad default: (row: 3, col: 12) 29 | 30 | © 2017 - 2024 PoomSmart 31 | 32 | 33 | cell 34 | PSEditTextCell 35 | detail 36 | PSDetailController 37 | default 38 | 39 | defaults 40 | com.PS.EmojiLayout 41 | PostNotification 42 | com.PS.EmojiLayout/ReloadPrefs 43 | key 44 | rows 45 | placeholder 46 | emoji per row 47 | isNumeric 48 | 49 | 50 | 51 | cell 52 | PSEditTextCell 53 | detail 54 | PSDetailController 55 | default 56 | 57 | defaults 58 | com.PS.EmojiLayout 59 | PostNotification 60 | com.PS.EmojiLayout/ReloadPrefs 61 | key 62 | columns 63 | placeholder 64 | emoji per column 65 | isNumeric 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PoomSmart/EmojiLayout/bb641d6da9a94edd7c0f9239496a02167062a249/layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout.png -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PoomSmart/EmojiLayout/bb641d6da9a94edd7c0f9239496a02167062a249/layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout@2x.png -------------------------------------------------------------------------------- /layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PoomSmart/EmojiLayout/bb641d6da9a94edd7c0f9239496a02167062a249/layout/Library/PreferenceLoader/Preferences/EmojiLayout/EmojiLayout@3x.png --------------------------------------------------------------------------------