React Native显示点9图片

作者: 这真不是玩笑 | 来源:发表于2017-05-24 15:47 被阅读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

    相关文章

      网友评论

        本文标题:React Native显示点9图片

        本文链接:https://www.haomeiwen.com/subject/tzqoxxtx.html