React NativeReact-Native 开发阵营React Native开发经验集

React Native显示点9图片

2017-05-24  本文已影响961人  这真不是玩笑

1.背景

本文使用的RN(使用RN表示React Native)的版本为0.44版本。在应用的开发过程,可能会遇到这么一种场景,就是在图片的拉伸过程中,需要保持部分区域不被拉伸,而部分区域需要进行拉伸。比如IM中聊天的背景气泡等。那么这个时候我们就可能需要使用到点9图片。那么在RN中,该如何使用点9图片呢?

2.RN上显示点9图片的思路

首先既然是图片,那么在RN中肯定是需要在组件Image中进行显示,那么RN的Image可以同时支持Android和ios平台的点9图片的制作和显示吗?我们去官方的Api文档上找找看。在RN的文档上我们看到了这样的介绍

ios
capInsets {top: number, left: number, bottom: number, right: number}
当图片被缩放的时候,capInsets指定的角上的尺寸会被固定而不进行缩放,而中间和边上其他的部分则会被拉伸。这在制作一些可变大小的圆角按钮、阴影、以及其它资源的时候非常有用(译注:这就是常说的九宫格或者.9图。了解更多信息,可以参见[苹果官方文档]

可以看到RN的Image组件是可以直接支持capInsets属性,对我们需要的图片进行对应的拉伸操作,这与ios原生的使用是一样的,那么在Android平台上该如何使用呢?很遗憾,在RN上并没有这方面的介绍。
  做过Android原生开发的可能知道,在Android平台上是可以通过工具制作点9图片,然后作为背景图片直接使用,那么按照这个思路,我们可以在Android封装对应的组件,然后在Android平台上要使用的时候就直接使用制作好的点9图片,而在ios平台上我们使用capInsets属性。

3.React Native 9patch image

在这里,我们找到了一个封装好的开源组件,Github地址:https://github.com/rusfearuth/react-native-9patch-image 我们来看下它在Android平台下的封装思路

public class RCTImageCapInsetManager extends SimpleViewManager<RCTImageCapInsetView> {
    @Override
    public String getName() {
        return "RCTImageCapInset";
    }

    @Override
    protected RCTImageCapInsetView createViewInstance(ThemedReactContext reactContext) {
        return new RCTImageCapInsetView(reactContext);
    }

    @ReactProp(name = "source")
    public void setSource(final RCTImageCapInsetView view, ReadableMap source) {
        String uri = source.getString("uri");
        view.setSource(uri);
    }
}

首先从source中获取uri的地址,然后将其赋值给这里的RCTImageCapInsetView,而对于RCTImageCapInsetView

public class RCTImageCapInsetView extends ImageView {
    private String mUri;

    public RCTImageCapInsetView(Context context) {
        super(context);
    }

    public void setSource(String uri) {
        mUri = uri;
        reload();
    }

    public void reload() {
        Integer resId = null;
        if (getImageCache().has(mUri)) {
            resId = getImageCache().get(mUri);
            if (resId == null) {
                getImageCache().remove(mUri);
            }
        }

        if (resId == null) {
            resId = getResourceDrawableId(mUri);
            getImageCache().put(mUri, resId);
        }

        setBackgroundResource(resId);
    }

    private @NonNull Integer getResourceDrawableId(@NonNull final String aName) {
        if (aName == null || aName.isEmpty()) {
                return 0;
        }

        final String name = aName.toLowerCase().replace("-", "_");

        return getResources().getIdentifier(
                name,
                "drawable",
                getContext().getPackageName()
        );
    }

    private RCTImageCache getImageCache()
    {
        return RCTImageCache.getInstance();
    }
}

RCTImageCapInsetView的本质是一个ImageView,获取到uri的名称,然后在drawable之中查找到对应的id名称,最后得到图片资源作为ImageView背景,跟我们在Android原生上使用点9图片的方式是一样的。

4.制作点9图片

4.1 Android平台下制作

在这里我们用到的是Android上默认的logo图片

ic_launcher.png

  将其赋值到res/drawable目录下,并将其改名为image.9.png,在android studio中双击打开它,选择9-patch模式

image.png

  这个时候我们就可以直接在android studio直接进行点9图片的制作,当然我们也可以打开android sdk中提供的点9图片制作工具进行制作,工具路径为:/Users/hzl/Library/Android/sdk/tools/draw9patch 至于如何点9图片的上下左右边界代表的意思,这里不作过多的阐述,可以通过百度,Google等去搜索相关的介绍。这样Android平台上的点9图片就制作完成了。

4.2 ios平台下制作

在上面我们制作了Android平台下的点9图片,那么在ios平台上,对应的capInsets属性是多少呢?我们把鼠标悬停在边界上

image.png image.png

可以看到Horizontal Patch:29-66px,那么对应的capInsets属性中的left和right就是29和29(95-66=29,其中95是原始图片的宽),同理根据Vertical Patch:40-86px,可以知道capInsets属性中的top和bottom就是40和9

5.RN上显示点9图片

在上面中我们制作好了对应的点9图片,那么我们分别在Android和ios平台上看下效果如果。

import React, {Component} from 'react';
import {View, Platform} from 'react-native';
import NinePatchView from 'react-native-9patch-image';

export default class Main extends Component {

    render() {
        return (
            <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
                <NinePatchView
                    style={{width: 200, height: 200}}
                    source={Platform.OS === 'android' ? {uri: 'image'} : require('./image.png')}
                    capInsets={{top: 40, left: 29, bottom: 9, right: 29}}/>
            </View>)
    }
}

这里要特别注意的是Android平台要使用Release版本的apk才可以看到效果,至于如何打包Android Release版本apk,可以去看下RN官方文档上的介绍,http://reactnative.cn/docs/0.43/signed-apk-android.html#content

ios.png android.png

  可以看到,两个平台上的显示效果是一致的。

6.最后

文章中使用的例子已经上传了Github:https://github.com/hzl123456/NinePatchView

上一篇下一篇

猜你喜欢

热点阅读