Merge branch 'feature/slider' into 'master'
Feature/slider See merge request !18
This commit is contained in:
		| @@ -4,7 +4,7 @@ android { | ||||
|     compileSdkVersion 29 | ||||
|     buildToolsVersion '29.0.2' | ||||
|     defaultConfig { | ||||
|         applicationId "com.github.penfeizhou.doric" | ||||
|         applicationId "pub.doric.demo" | ||||
|         minSdkVersion 16 | ||||
|         targetSdkVersion 29 | ||||
|         versionCode 1 | ||||
|   | ||||
| @@ -19,7 +19,7 @@ import android.graphics.drawable.Drawable; | ||||
|  | ||||
| import androidx.annotation.Nullable; | ||||
|  | ||||
| import android.view.ViewGroup; | ||||
| import android.text.TextUtils; | ||||
| import android.widget.ImageView; | ||||
|  | ||||
| import com.bumptech.glide.Glide; | ||||
| @@ -31,7 +31,7 @@ import com.bumptech.glide.request.target.Target; | ||||
| import pub.doric.DoricContext; | ||||
| import pub.doric.extension.bridge.DoricPlugin; | ||||
|  | ||||
| import com.github.pengfeizhou.jscore.JSObject; | ||||
| import com.github.pengfeizhou.jscore.JSONBuilder; | ||||
| import com.github.pengfeizhou.jscore.JSValue; | ||||
|  | ||||
| /** | ||||
| @@ -41,6 +41,8 @@ import com.github.pengfeizhou.jscore.JSValue; | ||||
|  */ | ||||
| @DoricPlugin(name = "Image") | ||||
| public class ImageNode extends ViewNode<ImageView> { | ||||
|     private String loadCallbackId = ""; | ||||
|  | ||||
|     public ImageNode(DoricContext doricContext) { | ||||
|         super(doricContext); | ||||
|     } | ||||
| @@ -52,22 +54,51 @@ public class ImageNode extends ViewNode<ImageView> { | ||||
|  | ||||
|     @Override | ||||
|     protected void blend(ImageView view, String name, JSValue prop) { | ||||
|         if ("imageUrl".equals(name)) { | ||||
|             Glide.with(getContext()).load(prop.asString().value()) | ||||
|                     .listener(new RequestListener<Drawable>() { | ||||
|                         @Override | ||||
|                         public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { | ||||
|                             return false; | ||||
|                         } | ||||
|         switch (name) { | ||||
|             case "imageUrl": | ||||
|                 Glide.with(getContext()).load(prop.asString().value()) | ||||
|                         .listener(new RequestListener<Drawable>() { | ||||
|                             @Override | ||||
|                             public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { | ||||
|                                 if (!TextUtils.isEmpty(loadCallbackId)) { | ||||
|                                     callJSResponse(loadCallbackId); | ||||
|                                 } | ||||
|                                 return false; | ||||
|                             } | ||||
|  | ||||
|                         @Override | ||||
|                         public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { | ||||
|                             return false; | ||||
|                         } | ||||
|                     }) | ||||
|                     .into(view); | ||||
|         } else { | ||||
|             super.blend(view, name, prop); | ||||
|                             @Override | ||||
|                             public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { | ||||
|                                 if (!TextUtils.isEmpty(loadCallbackId)) { | ||||
|                                     callJSResponse(loadCallbackId, new JSONBuilder() | ||||
|                                             .put("width", resource.getIntrinsicWidth()) | ||||
|                                             .put("height", resource.getIntrinsicHeight()) | ||||
|                                             .toJSONObject()); | ||||
|                                 } | ||||
|                                 return false; | ||||
|                             } | ||||
|                         }) | ||||
|                         .into(view); | ||||
|                 break; | ||||
|             case "scaleType": | ||||
|                 int scaleType = prop.asNumber().toInt(); | ||||
|                 switch (scaleType) { | ||||
|                     case 1: | ||||
|                         view.setScaleType(ImageView.ScaleType.FIT_CENTER); | ||||
|                         break; | ||||
|                     case 2: | ||||
|                         view.setScaleType(ImageView.ScaleType.CENTER_CROP); | ||||
|                         break; | ||||
|                     default: | ||||
|                         view.setScaleType(ImageView.ScaleType.FIT_XY); | ||||
|                         break; | ||||
|                 } | ||||
|                 break; | ||||
|             case "loadCallback": | ||||
|                 this.loadCallbackId = prop.asString().value(); | ||||
|                 break; | ||||
|             default: | ||||
|                 super.blend(view, name, prop); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -57,6 +57,8 @@ public class TextNode extends ViewNode<TextView> { | ||||
|             case "textAlignment": | ||||
|                 view.setGravity(prop.asNumber().toInt() | Gravity.CENTER_VERTICAL); | ||||
|                 break; | ||||
|             case "numberOfLines": | ||||
|                 break; | ||||
|             default: | ||||
|                 super.blend(view, name, prop); | ||||
|                 break; | ||||
|   | ||||
| @@ -135,12 +135,6 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent, | ||||
|      */ | ||||
|     private VelocityTracker mVelocityTracker; | ||||
|  | ||||
|     /** | ||||
|      * When set to true, the scroll view measure its child to make it fill the currently | ||||
|      * visible area. | ||||
|      */ | ||||
|     private boolean mFillViewport; | ||||
|  | ||||
|     /** | ||||
|      * Whether arrow scrolling is animated. | ||||
|      */ | ||||
| @@ -203,9 +197,6 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent, | ||||
|  | ||||
|         final TypedArray a = context.obtainStyledAttributes( | ||||
|                 attrs, SCROLLVIEW_STYLEABLE, defStyleAttr, 0); | ||||
|  | ||||
|         setFillViewport(a.getBoolean(0, false)); | ||||
|  | ||||
|         a.recycle(); | ||||
|  | ||||
|         mParentHelper = new NestedScrollingParentHelper(this); | ||||
| @@ -513,30 +504,6 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent, | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Indicates whether this ScrollView's content is stretched to fill the viewport. | ||||
|      * | ||||
|      * @return True if the content fills the viewport, false otherwise. | ||||
|      * @attr name android:fillViewport | ||||
|      */ | ||||
|     public boolean isFillViewport() { | ||||
|         return mFillViewport; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set whether this ScrollView should stretch its content height to fill the viewport or not. | ||||
|      * | ||||
|      * @param fillViewport True to stretch the content's height to the viewport's | ||||
|      *                     boundaries, false otherwise. | ||||
|      * @attr name android:fillViewport | ||||
|      */ | ||||
|     public void setFillViewport(boolean fillViewport) { | ||||
|         if (fillViewport != mFillViewport) { | ||||
|             mFillViewport = fillViewport; | ||||
|             requestLayout(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Whether arrow scrolling will animate its transition. | ||||
|      */ | ||||
| @@ -566,10 +533,6 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent, | ||||
|     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | ||||
|         super.onMeasure(widthMeasureSpec, heightMeasureSpec); | ||||
|  | ||||
|         if (!mFillViewport) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final int widthMode = MeasureSpec.getMode(widthMeasureSpec); | ||||
|         final int heightMode = MeasureSpec.getMode(heightMeasureSpec); | ||||
|         if (heightMode == MeasureSpec.UNSPECIFIED && widthMode == MeasureSpec.UNSPECIFIED) { | ||||
| @@ -587,14 +550,17 @@ public class HVScrollView extends FrameLayout implements NestedScrollingParent, | ||||
|             int childWidthMeasureSpec; | ||||
|             int childHeightMeasureSpec; | ||||
|             final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); | ||||
|             if (child.getMeasuredWidth() < width) { | ||||
|             if (lp.width != ViewGroup.LayoutParams.MATCH_PARENT && lp.height != ViewGroup.LayoutParams.MATCH_PARENT) { | ||||
|                 return; | ||||
|             } | ||||
|             if (child.getMeasuredWidth() < width && lp.width == ViewGroup.LayoutParams.MATCH_PARENT) { | ||||
|                 childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); | ||||
|             } else { | ||||
|                 widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); | ||||
|                 childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, | ||||
|                         getPaddingLeft() + getPaddingRight(), lp.width); | ||||
|             } | ||||
|             if (child.getMeasuredHeight() < height) { | ||||
|             if (child.getMeasuredHeight() < height && lp.height == ViewGroup.LayoutParams.MATCH_PARENT) { | ||||
|                 childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); | ||||
|             } else { | ||||
|                 heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); | ||||
|   | ||||
| @@ -6,4 +6,5 @@ export default [ | ||||
|     'src/SliderDemo', | ||||
|     'src/LayoutDemo', | ||||
|     'src/EffectsDemo', | ||||
|     'src/ImageDemo', | ||||
| ] | ||||
| @@ -1,6 +1,6 @@ | ||||
|  | ||||
| import { Group, Panel, Text, text, gravity, Color, Stack, LayoutSpec, vlayout, hlayout, scroller, IVLayout, IHLayout, layoutConfig } from "doric"; | ||||
| import { colors } from "./colorutils"; | ||||
| import { colors } from "./utils"; | ||||
|  | ||||
|  | ||||
| function box(idx = 0) { | ||||
| @@ -361,7 +361,7 @@ class EffectsDemo extends Panel { | ||||
|                 it.space = 20 | ||||
|             }), | ||||
|         ).also(it => { | ||||
|             it.layoutConfig = layoutConfig().wrap() | ||||
|             it.layoutConfig = layoutConfig().atmost() | ||||
|         }).in(rootView) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										64
									
								
								demo/src/ImageDemo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								demo/src/ImageDemo.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType } from "doric"; | ||||
| import { colors, label } from "./utils"; | ||||
| const imageUrl = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574244792703&di=c49ed8cd284c367fa8f00065a85428bd&imgtype=0&src=http%3A%2F%2Fimg3.iqilu.com%2Fdata%2Fattachment%2Fforum%2F201308%2F21%2F201709zikkhkjh7dgfi9f0.jpg' | ||||
| @Entry | ||||
| class ImageDemo extends Panel { | ||||
|     build(rootView: Group): void { | ||||
|         scroller(vlayout([ | ||||
|             text({ | ||||
|                 text: "Image Demo", | ||||
|                 layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), | ||||
|                 textSize: 30, | ||||
|                 textColor: Color.WHITE, | ||||
|                 bgColor: colors[1], | ||||
|                 textAlignment: gravity().center(), | ||||
|                 height: 50, | ||||
|             }), | ||||
|             label('ScaleToFill'), | ||||
|             image({ | ||||
|                 imageUrl, | ||||
|                 width: 300, | ||||
|                 height: 300, | ||||
|                 border: { | ||||
|                     width: 2, | ||||
|                     color: Color.GRAY, | ||||
|                 }, | ||||
|                 scaleType: ScaleType.ScaleToFill, | ||||
|                 layoutConfig: layoutConfig().exactly(), | ||||
|                 loadCallback: (ret) => { | ||||
|                     log('loadCallback', ret) | ||||
|                 } | ||||
|             }), | ||||
|             label('ScaleAspectFit'), | ||||
|             image({ | ||||
|                 imageUrl, | ||||
|                 width: 300, | ||||
|                 height: 300, | ||||
|                 border: { | ||||
|                     width: 2, | ||||
|                     color: Color.GRAY, | ||||
|                 }, | ||||
|                 scaleType: ScaleType.ScaleAspectFit, | ||||
|                 layoutConfig: layoutConfig().exactly(), | ||||
|             }), | ||||
|             label('ScaleAspectFill'), | ||||
|             image({ | ||||
|                 imageUrl, | ||||
|                 width: 300, | ||||
|                 height: 300, | ||||
|                 border: { | ||||
|                     width: 2, | ||||
|                     color: Color.GRAY, | ||||
|                 }, | ||||
|                 scaleType: ScaleType.ScaleAspectFill, | ||||
|                 layoutConfig: layoutConfig().exactly(), | ||||
|             }), | ||||
|         ]).apply({ | ||||
|             layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), | ||||
|             gravity: gravity().center(), | ||||
|             space: 10, | ||||
|         } as IVLayout)).apply({ | ||||
|             layoutConfig: layoutConfig().atmost(), | ||||
|         }).in(rootView) | ||||
|     } | ||||
| } | ||||
| @@ -1,11 +1,13 @@ | ||||
| import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, slider, slideItem, image, layoutConfig } from "doric"; | ||||
| import { colors } from "./colorutils"; | ||||
| import { colors } from "./utils"; | ||||
|  | ||||
| const imageUrls = [ | ||||
|     'http://b.hiphotos.baidu.com/image/pic/item/908fa0ec08fa513db777cf78376d55fbb3fbd9b3.jpg', | ||||
|     'http://f.hiphotos.baidu.com/image/pic/item/0e2442a7d933c8956c0e8eeadb1373f08202002a.jpg', | ||||
|     'http://f.hiphotos.baidu.com/image/pic/item/b151f8198618367aa7f3cc7424738bd4b31ce525.jpg', | ||||
|     'http://b.hiphotos.baidu.com/image/pic/item/0eb30f2442a7d9337119f7dba74bd11372f001e0.jpg', | ||||
|     'http://a.hiphotos.baidu.com/image/h%3D300/sign=b38f3fc35b0fd9f9bf175369152cd42b/9a504fc2d5628535bdaac29e9aef76c6a6ef63c2.jpg', | ||||
|     'http://h.hiphotos.baidu.com/image/pic/item/810a19d8bc3eb1354c94a704ac1ea8d3fd1f4439.jpg', | ||||
|     'http://calonye.com/wp-content/uploads/2015/08/0-wx_fmtgiftpwebpwxfrom5wx_lazy1-9.gif', | ||||
|     'http://hbimg.b0.upaiyun.com/ca29ea125b7f2d580f573e48eb594b1ef509757f34a08-m0hK45_fw658', | ||||
|     'https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png', | ||||
| @@ -31,7 +33,7 @@ class SliderPanel extends Panel { | ||||
|                 renderPage: (idx) => { | ||||
|                     return slideItem(image({ | ||||
|                         imageUrl: imageUrls[idx % imageUrls.length], | ||||
|                         layoutConfig: layoutConfig().wrap().a(gravity().center()), | ||||
|                         layoutConfig: layoutConfig().w(LayoutSpec.WRAP_CONTENT).h(LayoutSpec.WRAP_CONTENT).a(gravity().center()), | ||||
|                     })).also(it => { | ||||
|                         let start = idx | ||||
|                         it.onClick = () => { | ||||
|   | ||||
| @@ -1,14 +0,0 @@ | ||||
| import { Color } from "doric"; | ||||
|  | ||||
| export const colors = [ | ||||
|     "#70a1ff", | ||||
|     "#7bed9f", | ||||
|     "#ff6b81", | ||||
|     "#a4b0be", | ||||
|     "#f0932b", | ||||
|     "#eb4d4b", | ||||
|     "#6ab04c", | ||||
|     "#e056fd", | ||||
|     "#686de0", | ||||
|     "#30336b", | ||||
| ].map(e => Color.parse(e)) | ||||
							
								
								
									
										36
									
								
								demo/src/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								demo/src/utils.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| import { Color, text, Stack, Text } from "doric"; | ||||
|  | ||||
| export const colors = [ | ||||
|     "#70a1ff", | ||||
|     "#7bed9f", | ||||
|     "#ff6b81", | ||||
|     "#a4b0be", | ||||
|     "#f0932b", | ||||
|     "#eb4d4b", | ||||
|     "#6ab04c", | ||||
|     "#e056fd", | ||||
|     "#686de0", | ||||
|     "#30336b", | ||||
| ].map(e => Color.parse(e)) | ||||
|  | ||||
| export function label(str: string) { | ||||
|     return text({ | ||||
|         text: str, | ||||
|         textSize: 16, | ||||
|     }) | ||||
| } | ||||
|  | ||||
| export function box(idx = 0) { | ||||
|     return (new Stack).also(it => { | ||||
|         it.width = it.height = 20 | ||||
|         it.bgColor = colors[idx || 0] | ||||
|     }) | ||||
| } | ||||
| export function boxStr(str: string, idx = 0) { | ||||
|     return (new Text).also(it => { | ||||
|         it.width = it.height = 20 | ||||
|         it.text = str | ||||
|         it.textColor = Color.WHITE | ||||
|         it.bgColor = colors[idx || 0] | ||||
|     }) | ||||
| } | ||||
| @@ -153,8 +153,8 @@ | ||||
| 				E2334AF222E9D2060098A085 /* ViewController.m */, | ||||
| 				E2334AF422E9D2060098A085 /* Main.storyboard */, | ||||
| 				E2334AF722E9D2070098A085 /* Assets.xcassets */, | ||||
| 				E2334AF922E9D2070098A085 /* LaunchScreen.storyboard */, | ||||
| 				E2334AFC22E9D2070098A085 /* Info.plist */, | ||||
| 				E2334AF922E9D2070098A085 /* LaunchScreen.storyboard */, | ||||
| 				E2334AFD22E9D2070098A085 /* main.m */, | ||||
| 				D751D19E97EF4EDD7588FEBE /* DemoVC.m */, | ||||
| 				D751DDEC114E037231257E64 /* DemoVC.h */, | ||||
|   | ||||
| @@ -34,6 +34,13 @@ | ||||
| 		<string>UIInterfaceOrientationLandscapeLeft</string> | ||||
| 		<string>UIInterfaceOrientationLandscapeRight</string> | ||||
| 	</array> | ||||
| 	<key>NSAppTransportSecurity</key> | ||||
| 	<dict> | ||||
| 		<key>NSAllowsArbitraryLoads</key> | ||||
| 		<true/> | ||||
| 	</dict> | ||||
| 	<key>LSApplicationCategoryType</key> | ||||
| 	<string></string> | ||||
| 	<key>UISupportedInterfaceOrientations~ipad</key> | ||||
| 	<array> | ||||
| 		<string>UIInterfaceOrientationPortrait</string> | ||||
|   | ||||
| @@ -21,21 +21,57 @@ | ||||
| // | ||||
| 
 | ||||
| #import "DoricImageNode.h" | ||||
| #import "Doric.h" | ||||
| #import <SDWebImage/SDWebImage.h> | ||||
| 
 | ||||
| @interface DoricImageNode () | ||||
| @property(nonatomic, copy) NSString *loadCallbackId; | ||||
| @end | ||||
| 
 | ||||
| @implementation DoricImageNode | ||||
| 
 | ||||
| - (UIImageView *)build { | ||||
|     return [[UIImageView alloc] init]; | ||||
|     return [[UIImageView new] also:^(UIImageView *it) { | ||||
|         it.clipsToBounds = YES; | ||||
|     }]; | ||||
| } | ||||
| 
 | ||||
| - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id)prop { | ||||
|     if ([name isEqualToString:@"imageUrl"]) { | ||||
|     if ([@"imageUrl" isEqualToString:name]) { | ||||
|         __weak typeof(self) _self = self; | ||||
|         [view sd_setImageWithURL:[NSURL URLWithString:prop] completed:^(UIImage *_Nullable image, NSError *_Nullable error, SDImageCacheType cacheType, NSURL *_Nullable imageURL) { | ||||
|             __strong typeof(_self) self = _self; | ||||
|             [self requestLayout]; | ||||
|             if (error) { | ||||
|                 if (self.loadCallbackId.length > 0) { | ||||
|                     [self callJSResponse:self.loadCallbackId, nil]; | ||||
|                 } | ||||
|             } else { | ||||
|                 if (self.loadCallbackId.length > 0) { | ||||
|                     [self callJSResponse:self.loadCallbackId, | ||||
|                                          @{@"width": @(image.size.width), @"height": @(image.size.height)}, | ||||
|                                     nil]; | ||||
|                 } | ||||
|                 [self requestLayout]; | ||||
|             } | ||||
| 
 | ||||
|         }]; | ||||
|     } else if ([@"scaleType" isEqualToString:name]) { | ||||
|         switch ([prop integerValue]) { | ||||
|             case 1: { | ||||
|                 self.view.contentMode = UIViewContentModeScaleAspectFit; | ||||
|                 break; | ||||
|             } | ||||
|             case 2: { | ||||
|                 self.view.contentMode = UIViewContentModeScaleAspectFill; | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 self.view.contentMode = UIViewContentModeScaleToFill; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else if ([@"loadCallback" isEqualToString:name]) { | ||||
|         self.loadCallbackId = prop; | ||||
|     } else { | ||||
|         [super blendView:view forPropName:name propValue:prop]; | ||||
|     } | ||||
|   | ||||
| @@ -39,6 +39,7 @@ - (instancetype)initWithContext:(DoricContext *)doricContext { | ||||
| - (void)initWithSuperNode:(DoricSuperNode *)superNode { | ||||
|     [super initWithSuperNode:superNode]; | ||||
|     self.reusable = YES; | ||||
|     self.view.clipsToBounds = YES; | ||||
| } | ||||
| 
 | ||||
| - (DoricStackView *)build { | ||||
|   | ||||
| @@ -152,4 +152,7 @@ - (void)clearSubModel { | ||||
| - (DoricViewNode *)subNodeWithViewId:(NSString *)viewId { | ||||
|     return nil; | ||||
| } | ||||
| - (void)requestLayout { | ||||
|     [self.view setNeedsLayout]; | ||||
| } | ||||
| @end | ||||
| @@ -23,10 +23,13 @@ | ||||
| #import "DoricTextNode.h" | ||||
| #import "DoricUtil.h" | ||||
| #import "DoricGroupNode.h" | ||||
| #import "Doric.h" | ||||
| 
 | ||||
| @implementation DoricTextNode | ||||
| - (UILabel *)build { | ||||
|     return [[UILabel alloc] init]; | ||||
|     return [[[UILabel alloc] init] also:^(UILabel *it) { | ||||
|         it.textAlignment = NSTextAlignmentCenter; | ||||
|     }]; | ||||
| } | ||||
| 
 | ||||
| - (void)blendView:(UILabel *)view forPropName:(NSString *)name propValue:(id)prop { | ||||
|   | ||||
| @@ -42,11 +42,25 @@ export class Text extends View implements IText { | ||||
|     textAlignment?: Gravity | ||||
| } | ||||
|  | ||||
| export enum ScaleType { | ||||
|     ScaleToFill = 0, | ||||
|     ScaleAspectFit, | ||||
|     ScaleAspectFill, | ||||
| } | ||||
|  | ||||
| export interface IImage extends IView { | ||||
|     imageUrl?: string | ||||
|     scaleType?: ScaleType | ||||
|     loadCallback?: (image: { width: number; height: number } | undefined) => void | ||||
| } | ||||
|  | ||||
| export class Image extends View implements IImage { | ||||
|     @Property | ||||
|     imageUrl?: string | ||||
|  | ||||
|     @Property | ||||
|     scaleType?: ScaleType | ||||
|  | ||||
|     @Property | ||||
|     loadCallback?: (image: { width: number; height: number } | undefined) => void | ||||
| } | ||||
		Reference in New Issue
	
	Block a user