iOS端关于Weex填坑指南,持续更新中...

前提,我们是使用Weex以及EROS搭建的框架,具体使用请参考官方文档:
Weex官方文档,EROS官方文档。

长话短说,很晚了,直接上代码:

1、实现类似淘宝的tabbar

需求描述:就是做一个类似淘宝tabbar的效果,tabarItem的第一个图标和标题,在未选择的时候,和其他的一样,有一个图标和名称,当选中的时候,没有名称,只有一个图标,图标尺寸变大。

解决方案:直接对原生的UITabBarItem进行修改,可以修改里面的图片尺寸和大小,文字的颜色等。

文件目录:Benmu-iOS-Library/Source/BMController/BaseVc/BMTabBarController.m
修改代码:
configItems方法的最后面加上

 //---设置类似淘宝的tababr
    UITabBarItem *itemFirst = [self.tabBar.items objectAtIndex:0];
    itemFirst.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
    [itemFirst setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor colorWithRed:0 / 255.0 green:0 / 255.0 blue:0 / 255.0 alpha:0]} forState:UIControlStateSelected];

然后下面这个方法进行修改

/** tabbar index change */
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
//    WXLogInfo(@"Dealloc >>>>>>>>>>>>>>>>>>>>>>>: %li",self.selectedIndex);
    for (int i = 0; i < self.tabBar.items.count; i++) {
        UITabBarItem *tmpItem = [self.tabBar.items objectAtIndex:i];
       
        if (item == tmpItem) {
            UITabBarItem *itemFirst = [self.tabBar.items objectAtIndex:0];
            //---设置类似淘宝的tababr
            if (i==0) {
                itemFirst.imageInsets=UIEdgeInsetsMake(6, 0, -6, 0);
                [itemFirst setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor colorWithRed:0 / 255.0 green:0 / 255.0 blue:0 / 255.0 alpha:0]} forState:UIControlStateSelected];
            }else{
                itemFirst.imageInsets=UIEdgeInsetsMake(0, 0, 0, 0);
            }
            [BMGlobalEventManager sendGlobalEvent:@"tabarSelected" params:@{@"selectedIndex":@(i)}];
            [[NSNotificationCenter defaultCenter] postNotificationName:K_BMTabbarChangeIndex object:@(i)];
            return;
        }
      
    }
}

实现效果图:


iOS端关于Weex填坑指南,持续更新中..._第1张图片
实现效果图

参考资料:
1、更改UITabBarItem图像的高度和宽度 位置调整
2、 tabbarItem字体及图片颜色设置

2、实现类似微博中间加号的tabbar

需求描述:就是做一个类似微博中间加号的tabbar,现在的微博已经改版了,看不到这个效果了,微博起初了一个版本的tabbar是这样的,tabbar中间的tabbarItem,只有一个加号的图标,点击图标,是弹出一个蒙层,上面有几个功能按钮。

Tips:其实这个可以按照我上面的那个方法实现,下面是我另外一种解决方案,大家可参考一下

解决方案:添加一个图片直接覆盖在中间的UITabBarItem上面

文件目录:Benmu-iOS-Library/Source/BMController/BaseVc/BMTabBarController.m
修改代码:
configItems方法的for循环里面加上

    if(i==2){
            CGSize imageSize = CGSizeMake(40, 40);
            UIImage *imageCenter =[UIImage imageNamed:@"addImage"];
            imageCenter = [self scaleToSize:imageCenter size:imageSize];
            item.image= [imageCenter imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            item.selectedImage = [imageCenter imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            item.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
//            item.imageInsets = UIEdgeInsetsMake(0, -10, -6, -10);
        }

代码如图所示:


iOS端关于Weex填坑指南,持续更新中..._第2张图片
具体位置如图所示

然后在加入下面的方法

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{    
    //---中间的加号
    if (viewController == self.viewControllers[2]) {
        [BMGlobalEventManager sendGlobalEvent:@"tabarCenter" params:@{@"selectedIndex":@(self.selectedIndex)}];
        return NO;
    }
    
    return YES;

}

讲点击加号的这个方法发射到Weex中,然后在weex中进行监听这个方法

const globalEvent = weex.requireModule('globalEvent')

/**
 * tababr中间加号
 * options
 */
// globalEvent.addEventListener('tabarCenter', function (options) {
globalEvent.addEventListener('tabarCenter', async (options) => {
    let selectStore = await getCache("selectStore");
    console.log('》》》》》》》》tabarCenter' + JSON.stringify(options));
    let params = { selectedIndex: options.selectedIndex };
    router.open({
        url: "/pages/tabarCenter.js",
        type: 'PRESENT',
        navShow: false,
        params: params,
    })
});

然后点击加号实现类似微博弹出的一个蒙层页面!

实现效果图:


iOS端关于Weex填坑指南,持续更新中..._第3张图片
类似微博的加号tababr

iOS端关于Weex填坑指南,持续更新中..._第4张图片
点击效果图

3、实现weex加载富文本

需求描述:APP中经常会用到加载富文本的问题,但是weex中并没有实现富文本的加载,这个坑就留给咱们自己踩了。我们遇到的是在商品详情页面里的一些商品信息,是后台解决返回的富文本,Weex官网的文档中展示这个的组件。

解决方案:自己封装一个原生组件,加载原生的webview。

新增一个LocalWebPage.h和LocalWebPage.m文件
目录:/Benmu-iOS-Library/Source/CustomerEvent/LocalWebPage.m

代码如下:
LocalWebPage.h

//
//  LocalWebPage.h
//  WeexDemo
//

//  Copyright © 2018年 taobao. All rights reserved.
//

#import 
#import "WXComponent.h"

@interface LocalWebPage : WXComponent

@end

LocalWebPage.m

//
//  LocalWebPage.m
//  WeexDemo
//
//  Copyright © 2018年 taobao. All rights reserved.
//


#import "LocalWebPage.h"
#import 
#import "WXUtility.h"
#import "WXURLRewriteProtocol.h"
#import "WXSDKEngine.h"
#import "BMMediatorManager.h"
#import "BMGlobalEventManager.h"



@interface LocalWebPage () 

@property (nonatomic, strong) JSContext *jsContext;
@property (nonatomic, strong) UIWebView *webview;
@property (nonatomic, assign) BOOL startLoadEvent;

@property (nonatomic, assign) BOOL finishLoadEvent;

@property (nonatomic, assign) BOOL failLoadEvent;

@property (nonatomic, assign) BOOL notifyEvent;
@property (nonatomic, strong) NSString *url;

@end

@implementation LocalWebPage
WX_EXPORT_METHOD(@selector(goBack))
WX_EXPORT_METHOD(@selector(reload))
WX_EXPORT_METHOD(@selector(goForward))

- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
{
    if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
        NSLog(@"%@",attributes);

        NSString* src = attributes[@"src"];
        self.url = src;
        _url = src;
        NSLog(@"%@",self.url);
    }
    return self;
}

- (UIView *)loadView
{
    return [[UIWebView alloc] init];
}

- (void)viewDidLoad
{
    _webview = (UIWebView *)self.view;
    _webview.delegate = self;
    _webview.allowsInlineMediaPlayback = YES;
    _webview.scalesPageToFit = YES;
    [_webview setBackgroundColor:[UIColor clearColor]];
//    _webview.userInteractionEnabled=NO;
    //禁止webView内部的scrollView的滚动
    _webview.scrollView.scrollEnabled = NO;
    //kvo监听webView内部的scrollView的contentSize
    [_webview.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
    
    _webview.opaque = NO;
//    _webview.height = 971;
    _jsContext = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    __weak typeof(self) weakSelf = self;
    _jsContext[@"$notifyWeex"] = ^(JSValue *data) {
        if (weakSelf.notifyEvent) {
            [weakSelf fireEvent:@"notify" params:[data toDictionary]];
        }
    };
    
    if (_url) {
        [self loadURL:_url];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (object == _webview.scrollView && [keyPath isEqualToString:@"contentSize"]) {
        NSLog(@"_webView.scrollView.contentSize %f %f", _webview.scrollView.contentSize.width, _webview.scrollView.contentSize.height);
        float height =_webview.scrollView.contentSize.height;
        float webHeight = self.webview.height;
        self.webview.height = height;
            if([self.webview.superview isKindOfClass: NSClassFromString(@"WXScrollerComponentView")]){
                UIScrollView* scroll = self.webview.superview;
               float scrollHeight =  scroll.contentSize.height - webHeight + height;
                scroll.contentSize = CGSizeMake(scroll.contentSize.width, scrollHeight);
            }
    }
}



//3.删除监听

- (void)dealloc
{
    [_webview.scrollView removeObserver:self forKeyPath:@"contentSize" ];
    
}

- (void)updateAttributes:(NSDictionary *)attributes
{
    if (attributes[@"src"]) {
        self.url = attributes[@"src"];
    }
}

- (void)addEvent:(NSString *)eventName
{
    if ([eventName isEqualToString:@"pagestart"]) {
        _startLoadEvent = YES;
    }
    else if ([eventName isEqualToString:@"pagefinish"]) {
        _finishLoadEvent = YES;
    }
    else if ([eventName isEqualToString:@"error"]) {
        _failLoadEvent = YES;
    }
}

- (void)setUrl:(NSString *)url
{
    NSString* newURL = [url copy];
    WX_REWRITE_URL(url, WXResourceTypeLink, self.weexInstance)
    if (!newURL) {
        return;
    }
    
    if (![newURL isEqualToString:_url]) {
        _url = newURL;
        if (_url) {
            [self loadURL:_url];
        }
    }
}

- (void)loadURL:(NSString *)url
{
    if (self.webview) {
//        NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
//        [self.webview loadRequest:request];
        [self.webview loadHTMLString:url baseURL:nil];
    }
}

- (void)reload
{
    [self.webview reload];
}

- (void)goBack
{
    if ([self.webview canGoBack]) {
        [self.webview goBack];
    }
}

- (void)goForward
{
    if ([self.webview canGoForward]) {
        [self.webview goForward];
    }
}

- (void)notifyWebview:(NSDictionary *) data
{
    NSString *json = [WXUtility JSONString:data];
    NSString *code = [NSString stringWithFormat:@"(function(){var evt=null;var data=%@;if(typeof CustomEvent==='function'){evt=new CustomEvent('notify',{detail:data})}else{evt=document.createEvent('CustomEvent');evt.initCustomEvent('notify',true,true,data)}document.dispatchEvent(evt)}())", json];
    [_jsContext evaluateScript:code];
}

#pragma mark Webview Delegate

- (NSMutableDictionary *)baseInfo
{
    NSMutableDictionary *info = [NSMutableDictionary new];
    [info setObject:self.webview.request.URL.absoluteString ?: @"" forKey:@"url"];
    [info setObject:[self.webview stringByEvaluatingJavaScriptFromString:@"document.title"] ?: @"" forKey:@"title"];
    [info setObject:@(self.webview.canGoBack) forKey:@"canGoBack"];
    [info setObject:@(self.webview.canGoForward) forKey:@"canGoForward"];
    return info;
}

- (void)webViewDidStartLoad:(UIWebView *)webView
{
    
}


- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    
    if (_finishLoadEvent) {
//        [self hideHUD];
        NSDictionary *data = [self baseInfo];
        [self fireEvent:@"pagefinish" params:data domChanges:@{@"attrs": @{@"src":self.webview.request.URL.absoluteString}}];
    }
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    if (_failLoadEvent) {
//        [self showHUDText:@"加载失败" withView:self.view];
        NSMutableDictionary *data = [self baseInfo];
        [data setObject:[error localizedDescription] forKey:@"errorMsg"];
        [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"errorCode"];
        
        NSString * urlString = error.userInfo[NSURLErrorFailingURLStringErrorKey];
        if (urlString) {
            // webview.request may not be the real error URL, must get from error.userInfo
            [data setObject:urlString forKey:@"url"];
            if (![urlString hasPrefix:@"http"]) {
                return;
            }
        }
        [self fireEvent:@"error" params:data];
    }
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if (_startLoadEvent) {
//        [self showWaitHint:@"正在加载..."];
        NSMutableDictionary *data = [NSMutableDictionary new];
        [data setObject:request.URL.absoluteString ?:@"" forKey:@"url"];
        [self fireEvent:@"pagestart" params:data];
    }
    return YES;
}


@end

上面代码中特别注意- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context这个方法中,进行了监听实时计算webview的高度,这个问题,在安卓中也是有点麻烦,需要实时计算。

这个类需要在BMConfigManager.m中进行引用

#import "LocalWebPage.h"

需要在+ (void)registerBmComponents这个方法里面进行注册

@"richweb":         NSStringFromClass([LocalWebPage class])

注册完成之后,就可以在weex中直接使用,相当方便

 

   return {
      richwebHeight: "1"
    };
  mounted() {
    let that = this
    event.on("richWebViewHeight", function(params) {
      let viewHeight = weex.config.env.deviceHeight;
      let viewWidth = weex.config.env.deviceWidth;
      that.richwebHeight = (params.height*750)/viewWidth
    });
  },
  computed: {
//这块ios,其实不需要计算高度,安卓是原生获取高度,传到weex里面,然后在设置富文本的高度。
    richwebStyle() {
      if (weex.config.env.platform != "android") {
        return {
        };
      } else {
        return {
          height: this.richwebHeight + "px"
        };
      }
    },
}
  methods: {
  getFullDescriptionWap() {
      if (!this.goodsDetail.fullDescriptionWap) {
        return;
      }
      // this.goodsDetail.fullDescriptionWap= "

1、加工工艺性:材料的加工工艺性直接影响到家具的生产。对于木质材料,在加工过程中,要考虑到其受水分的影响而产生的缩胀、各向异裂变性及多孔性等。塑料材料要考虑到其延展性、热塑变形等。玻璃材料要考虑到其热脆性、硬度等。

2、质地和外观质量:材料的质地和肌理决定了产品的外观质量的特殊感受。木材属于天然材料,纹理自然、美观,形象逼真,手感好,且易于加工、着色,是生产家具的上等材料。塑料及其合成材料具有模拟各种天然材料质地的特点,并且具有良好的着色性能,但其易于老化,易受热变形,用此生产家具,其使用寿命和使用范围受到限制。

3、经济性:家具材料的经济性包括材料的价格、材料的加工劳动消耗、材料的利用率及材料来源的丰富性。

4、强度:强度方面要考虑其握着力和抗劈性能及弹性模量。

5、表面装饰性能:一般情况下,表面装饰性能是指对其进行涂饰、胶贴、雕刻、着色、烫、烙等装饰的可行性。

"; // this.goodsDetail.fullDescriptionWap= "


"; // this.goodsDetail.fullDescriptionWap= ""; let temp = '
'; this.fullDescriptionWap = temp + this.goodsDetail.fullDescriptionWap + "
"; }, }

//这块ios,其实不需要计算高度,安卓是原生获取高度,传到weex里面,然后在设置富文本的高度。

在js下的config下面建一个全局的js文件,和原生进行数据传输,仅仅安卓需要或者这个高度,ios不需要
const globalEvent = weex.requireModule('globalEvent')
/**
 * 监听点击安卓richWebViewHeight
 */
globalEvent.addEventListener('richWebViewHeight', async (options) => {
    // console.log("richWebViewHeight",JSON.stringify(options));
    event.emit("richWebViewHeight", { height: options.richWebViewHeight });
});

4、键盘弹出,覆盖输入框

问题描述:在做一个新的项目的时候,需要一个问题,IOS端,键盘弹出,页面不会跟随一起上移动,这样就导致输入框遮挡键盘的问题,这个问题需要在iOS原生里面进行修改

解决方案:

1、文件目录:/Benmu-iOS-Library/Source/BMWeexExtension/WXEditComponent+BMExtend.h,在WXEditComponent+BMExtend.h里面新增一个方法- (void)bmEdit_keyboardWillHide:(NSNotification*)notification;

WXEditComponent+BMExtend.m里面实现这个方法

- (void)bmEdit_keyboardWillHide:(NSNotification*)notification {
    if (![self.view isFirstResponder]) {
        return;
    }
   
        UIView * rootView = self.weexInstance.rootView;
        if (!CGRectEqualToRect(self.weexInstance.frame, rootView.frame)) {
            [self setViewMovedUp:NO];
        }
        self.weexInstance.isRootViewFrozen = NO;
   
    if ([[self valueForKey:@"keyboardEvent"] boolValue]) {
        [self fireEvent:@"keyboard" params:@{ @"isShow": @NO }];
    }
}

2、文件目录/Benmu-iOS-Library/Source/BMWeexExtension/BMMethods.m,
在 BMMethods.m里面的exchangeWeexEditComponent方法里监听地调用这个方法

+ (void)exchangeWeexEditComponent
{
    [self bm_swizzle:[WXEditComponent class] Method:@selector(setAutofocus:) withMethod:@selector(bmEdit_setAutofocus:)];
    [self bm_swizzle:[WXEditComponent class] Method:@selector(initWithRef:type:styles:attributes:events:weexInstance:) withMethod:@selector(bmEdit_initWithRef:type:styles:attributes:events:weexInstance:)];
    [self bm_swizzle:[WXEditComponent class] Method:@selector(viewDidLoad) withMethod:@selector(bmEdit_viewDidLoad)];
    [self bm_swizzle:[WXEditComponent class] Method:@selector(keyboardWasShown:) withMethod:@selector(bmEdit_keyboardWasShown:)];
    [self bm_swizzle:[WXEditComponent class] Method:@selector(keyboardWillHide:) withMethod:@selector(bmEdit_keyboardWillHide:)];
}

5、状态栏颜色的修改

问题描述:但我们使用原生的导航栏的时候,我们就会发现这个导航栏的颜色,原生的提供了2种颜色,黑色和白色。在做项目中,我们经常需要修改这个颜色。

解决方案:

文件目录:/Benmu-iOS-Library/Source/BMController/BaseVc/BMNavigationController.m,在 BMNavigationController.m- (void)setupViews方法里设置一下:

 // 设置 navigationBar 背景颜色
    UIColor *setColor = [UIColor colorWithHexString:TK_PlatformInfo().page.navBarColor];
//    [self.navigationBar ex_setBackgroundColor:setColor?:K_NAV_BAR_COLOR];
    UIImage* image = [self createImageWithColor:setColor];
    [self.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
    [self.navigationBar setBackgroundColor:setColor];
- (UIImage *)createImageWithColor:(UIColor *)color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);
    UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
   
    return theImage;
}

6、实现Tabbar一级页面全屏蒙层的透明色修改

问题描述:其实在weexUI中,提供了蒙层的的组件,但是有一个问题,就是当这个在一级页面的时候,这个蒙层不能遮挡下面的tabar按钮,这个其实是不太合理的。

解决方案:通过present的跳转方式,从下面弹出一个页面,就可以了。但是在实际开发的过程中,有一个问题,就是没有这个新的页面的怎么设置,都不能设置透明色,这块就需要在原生里面进行修改了。

/Benmu-iOS-Library/Source/BMManager/Mediator/BMMediatorManager.m目录中,找到这个方法- (void)_openViewControllerWithRouterModel:(BMRouterModel *)routerModel weexInstance:(WXSDKInstance *)weexInstance

这个方法里面有一个/* 页面展现方式 */的判断,里面的这个宏K_ANIMATE_PRESENT,就是判断的present跳转方式,在这块进行修改一下,设置跳转后的页面是透明色

/* 页面展现方式 */      K_ANIMATE_PRESENT
elseif ([routerModel.typeisEqualToString:K_ANIMATE_PRESENT])
    {
//        BMNavigationController *navc = [[BMNavigationController alloc] initWithRootViewController:controller];
//        [self presentViewController:navc weexInstance:weexInstance];
       
        controller.view.backgroundColor = [UIColor clearColor];
        BMNavigationController *navc = [[BMNavigationController alloc] initWithRootViewController:controller];
        navc.modalPresentationStyle = UIModalPresentationOverFullScreen;
        controller.modalPresentationStyle = UIModalPresentationOverCurrentContext;
        [self presentViewController:navc weexInstance:weexInstance];
}

你可能感兴趣的:(iOS端关于Weex填坑指南,持续更新中...)