主要实现的效果为自定义图片显示组件到ReactNative中,加载使用Glide点击使用原生实现的图片浏览器进行放大
浏览.
先看效果
然后介绍代码相关:
环境 React-Native 0.59 Android 3.6 compileSdkVersion 28
首先是Native端:
创建 TTImageView
类 这个是我们要实现图片加载的控件
package com.ffy.tyc;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.support.v7.widget.AppCompatImageView;
/**
* 自定义到RN的原生图片加载组件
*/
public class TTImageView extends AppCompatImageView {
/**
* 保存远程的图片地址
*/
public String imageUrl = "";
//初始化
public TTImageView(Context context) {
super(context);
}
//imageUrl setter
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
/**
* 根据view来获取到对应引用的Activity
* @return Activity
*/
public Activity getActivity() {
Context context = getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
return (Activity)context;
}
context = ((ContextWrapper)context).getBaseContext();
}
return null;
}
}
然后根据RN的文档来创建 ViewManager
来装载它
package com.ffy.tyc;
import com.bumptech.glide.Glide;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.kudou.bigimage.ImagePreview;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* 对应的TTImageView的view manager
*/
public class TTImageViewManager extends SimpleViewManager<TTImageView> {
//自定义组件的名字
public static final String REACT_CLASS = "RCTTImageView";
//自定义event事件名tag
private static final int COMMAND_SCALE = 1;
@Nonnull
@Override
public String getName() {
return REACT_CLASS;
}
//创建实例
@Nonnull
@Override
protected TTImageView createViewInstance(@Nonnull ThemedReactContext reactContext) {
return new TTImageView(reactContext);
}
//创建rn中的attribute <RCTTImageView src=xxx>
@ReactProp(name = "src")
public void setSrc(TTImageView view, @Nullable String url){
view.setImageUrl(url);
Glide.with(view.getContext()).load(url).into(view);
}
//映射event操作
@Nullable
@Override
public Map<String, Integer> getCommandsMap() {
return MapBuilder.of(
"scale", COMMAND_SCALE
);
}
//接收到rn中过来的event
@Override
public void receiveCommand(@Nonnull TTImageView root, int commandId, @Nullable ReadableArray args) {
switch (commandId) {
case COMMAND_SCALE:{
//点击放大效果
ImagePreview.getInstance().
setFromImageView(root).
setContext(root.getActivity()).
setImage(root.imageUrl)
.start();
}
break;
}
}
}
TTImageViewManager
中主要是装载 TTImageView
和 导出一些操作的接口给RN
比如通过在RN中 <RCTTImageView src=xxx>
来触发 setSrc
的逻辑 里面就是通过传递value string给Glide
来实现加载网络图片
好了之后创建 package
package com.ffy.tyc;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
/**
* TTImageViewManager的Package
* 这个是为了注册TTImageViewManager到程序中
*/
public class TTImageViewPackage implements ReactPackage {
//这里填写需要注册的Manager - TTImageViewManager
@Nonnull
@Override
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new TTImageViewManager());
}
//这个是需要注册的Module 如果没有就设置为空 - Collections.emptyList()
@Nonnull
@Override
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
好了之后添加到 Application
中
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new TTImageViewPackage(),//加载自定义的组件
new MainReactPackage(),
new SplashScreenReactPackage(),
new CodePush(BuildConfig.CODEPUSH_KEY, getApplicationContext(), BuildConfig.DEBUG),
new RNCWebViewPackage(),
new FastImageViewPackage(),
new LinearGradientPackage(),
new RNSpinkitPackage(),
new AsyncStoragePackage(),
new VectorIconsPackage(),
new RNGestureHandlerPackage(),
new MainBridgeReactPackage()
);
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
JPushInterface.init(this
);
JPushInterface.setDebugMode(false);
OkHttpUtils.init(this);
}
}
到此 Native
端的任务就完成了
RN端
创建 ImageView.js
import React from "react";
import {
requireNativeComponent,
View,
UIManager,
findNodeHandle
} from "react-native";
const PropTypes = require("prop-types");
const iface = {
name: "RCTTImageView",
PropTypes: {
src: PropTypes.string,
...View.propTypes // include the default view properties 保留一些view的特性,比如flex
}
};
const RCTTImageView = requireNativeComponent("RCTTImageView", iface);
class TTImage extends React.Component {
scale = () => {
//发送event到native端
UIManager.dispatchViewManagerCommand(
this.getTTImageViewHandle(),
UIManager.getViewManagerConfig("RCTTImageView").Commands.scale,
null
);
};
//获取自定义的view节点传递给native端
getTTImageViewHandle = () => findNodeHandle(this.refs.image);
render() {
const { url } = this.props;
return (
<RCTTImageView
ref="image"
src={url}
style={{ width: 200, height: 200 }}
/>
);
}
}
export default TTImage;
这样就导出成组件使用了
// import TTImage from "../../component/ImageView";
<TouchableOpacity
onPress={() => {
this.handleClickTTImage();
}}
>
<TTImage
ref={c => {
this.ttimage = c;
}}
url="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1587639645275&di=a5dec78edefca81aadca063fcf765b59&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fmobile%2F2020-03-16%2F5e6f254d38c5c.jpg"
/>
</TouchableOpacity>
//点击
handleClickTTImage = () => {
this.ttimage.scale();
};
总结:
RN的官方文档说得并不详细(可能是我读的姿势有问题。。。) 但是搜索一下还是有很多相关内容 问题不大.