Life Cycle:
Communication:
Ref:
Ref:
Ref:
Ref:
Ref:
#import "RCTViewManager.h"@interface MyCustomViewManager : RCTViewManager@end
#import "MyCustomViewManager.h"#import "MyCustomView.h"@implementation MyCustomViewManagerRCT_EXPORT_MODULE()- (UIView *)view{ MyCustomView * theView; theView = [[MyCustomView alloc] initWithFrame:CGRectMake(0,0,10,10)]; return theView;}RCT_EXPORT_VIEW_PROPERTY(srcImagePath, NSString);RCT_EXPORT_VIEW_PROPERTY(cropImageWidth, NSInteger);RCT_EXPORT_VIEW_PROPERTY(cropImageHeight, NSInteger);RCT_EXPORT_VIEW_PROPERTY(textHeight, NSInteger);RCT_EXPORT_VIEW_PROPERTY(textFontSize, NSInteger);RCT_EXPORT_VIEW_PROPERTY(textFontFamily, NSString);RCT_EXPORT_VIEW_PROPERTY(textContent, NSString);@end
#import@interface MyCustomView : UIView@property (nonatomic) NSString* srcImagePath;@property (nonatomic) NSInteger cropImageWidth;@property (nonatomic) NSInteger cropImageHeight;@property (nonatomic) NSInteger textHeight;@property (nonatomic) NSInteger textFontSize;@property (nonatomic) NSString* textFontFamily;@property (nonatomic) NSString* textContent;@end
#import "MyCustomView.h"@implementation MyCustomView{}- (void)setTextHeight:(NSInteger)textHeight{ _textHeight = textHeight;}- (void)setTextFontSize:(NSInteger)textFontSize{ _textFontSize = textFontSize;}-(void)setTextFontFamily:(NSString *)textFontFamily{ _textFontFamily = textFontFamily;}-(void)setTextContent:(NSString *)textContent{ _textContent = textContent;}- (void)setCropImageHeight:(NSInteger)cropImageHeight{ _cropImageHeight = cropImageHeight;}- (void)setCropImageWidth:(NSInteger)cropImageWidth{ _cropImageWidth = cropImageWidth;}- (void)setSrcImagePath:(NSString *)srcImagePath{ _srcImagePath = srcImagePath; [self setNeedsDisplay];}- (void)drawRect:(CGRect)rect{ UIImage *srcImage = [UIImage imageWithContentsOfFile:_srcImagePath]; CGImageRef cgRef = srcImage.CGImage; CGFloat srcWidth = CGImageGetWidth(cgRef); CGFloat srcHeight = CGImageGetHeight(cgRef); CGImageRef imageRef = CGImageCreateWithImageInRect(cgRef,CGRectMake( srcWidth / 2 - _cropImageWidth / 2, srcHeight / 2 - _cropImageHeight / 2, srcWidth / 2 + _cropImageWidth / 2, srcHeight / 2 + _cropImageHeight / 2)); UIImage *cropImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); UIImageView *imageView = [[UIImageView alloc] init]; imageView.frame = CGRectMake(0, 0, _cropImageWidth, _cropImageHeight); [imageView setImage:cropImage]; [self addSubview:imageView]; UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, _cropImageHeight - _textHeight, _cropImageWidth, _textHeight)]; [textView setBackgroundColor:[UIColor blackColor]]; [textView setTextColor:[UIColor whiteColor]]; [textView setAlpha:0.5f]; [textView setFont:[UIFont fontWithName:_textFontFamily size:_textFontSize]]; [textView setText:_textContent]; [self addSubview:textView]; CGContextFillRect(UIGraphicsGetCurrentContext(), rect);}@end
/** * Created by NickChung on 5/17/16. */import React, {Component} from 'react';import {requireNativeComponent} from 'react-native';var NativeMyCustomView = requireNativeComponent('MyCustomView', MyCustomView);export default class MyCustomView extends Component { static propTypes = { srcImagePath: React.PropTypes.string, cropImageWidth: React.PropTypes.number, cropImageHeight: React.PropTypes.number, textFontSize: React.PropTypes.number, textFontHeight: React.PropTypes.number, textFontFamily: React.PropTypes.string, textContent: React.PropTypes.string }; render() { return; }}
/** * Created by NickChung on 5/16/16. */'use strict';var React = require('react-native');var { StyleSheet, Text, View, ListView, DeviceEventEmitter, NativeModules, Image, Dimensions, TouchableOpacity } = React;const EventEmitterMixin = require('react-event-emitter-mixin');const RealmRepo = require("./RealmRepo.js");const History = require("./History");const RNFS = require('react-native-fs');import Icon from 'react-native-vector-icons/FontAwesome';const TimerMixin = require('react-timer-mixin');var Modal = require('react-native-modalbox');var Overlay = require('react-native-overlay');import {Actions} from "react-native-router-flux";import Detail from './Detail'var deviceScreen = Dimensions.get('window');var _ = require('lodash');var Sound = require('react-native-sound');const RNS = NativeModules.RNSound;import MyCustView from './MyCustView'// Create our dataSource which will be displayed in the data listvar ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});var beaconState = [];var headState = {};var openHeadState = {};var lastBeaconId = "";var modalState = false;var s = null;var orderState = null;// The BeaconViewvar BeaconView = React.createClass({ mixins:[EventEmitterMixin], render: function() { try { let beacon = RealmRepo.getBeaconInfo(this.props.major, this.props.minor); if (beacon) { let content = beacon.triggercontent[0].content; let audio = beacon.triggercontent[1]; if (content) { let imageUri = RNFS.DocumentDirectoryPath + content.clientpath + content.filename; if(imageUri) { let title = content['title_' + RealmRepo.Locale().displayLang]; let artist = content['artist_' + RealmRepo.Locale().displayLang]; let effectiveRangeIn = beacon.effectiverangein; //let colorLevel = ['#FE9375', '#1DD5C0', '#00A8A7', '#C8C8C8']; let rssiLevel = [-5, -10, -20, -25]; //var color = "#C8C8C8"; let rssi = this.props.rssi; var desc, baseUrl, audioPath, placeHolder; var state = 0; var refImageId = content.contentid; var refAudioId = -1; var exTag = beacon.extag; var fontSize = 20; var lineHeight = 30; var locale = RealmRepo.Locale().displayLang; if(locale=='en' || locale=='pt') { fontSize = 16; lineHeight = 20; } placeHolder = '{' + content.clientpath + content.filename + '}'; baseUrl = RNFS.DocumentDirectoryPath + content.clientpath; desc = content["description_" + RealmRepo.Locale().displayLang].replace(placeHolder, content.filename); if (audio) { let audioContent = audio.content; if (audioContent) { refAudioId = audioContent.contentid; audioPath = RNFS.DocumentDirectoryPath + audioContent.clientpath + audioContent.filename.replace(".mp3", `_${RealmRepo.Locale().voiceLang}.mp3`); } } if (rssi >= effectiveRangeIn) { state = 1; } else if (rssi >= effectiveRangeIn + rssiLevel[0]) { //color = colorLevel[0]; } else if (rssi >= effectiveRangeIn + rssiLevel[1]) { //color = colorLevel[1]; } else if (rssi >= effectiveRangeIn + rssiLevel[2]) { //color = colorLevel[2]; } else if (rssi >= effectiveRangeIn + rssiLevel[3]) { //color = colorLevel[3]; } var findBeacon = _.find(beaconState, (o)=> { return o.beaconId == beacon.beaconid; }); if (findBeacon) { findBeacon.state = state; if (state == 1) { findBeacon.desc = desc; findBeacon.audioPath = audioPath; findBeacon.baseUrl = baseUrl; } } else { let newBeacon = { beaconId: beacon.beaconid, state: state, mode: 'auto', extag: exTag, refImageId: refImageId, refAudioId: refAudioId, from: 'leftMenuBall' }; if (state == 1) { newBeacon.desc = desc; newBeacon.audioPath = audioPath; newBeacon.baseUrl = baseUrl; } beaconState.push(newBeacon); } let bgColor = this.props.altRow ? '#9FADAD': '#88C1C1'; return ({ Actions.detail(); this.eventEmitter('emit','refreshDetail',{ extag: exTag, refImageId: refImageId, refAudioId: refAudioId, desc: desc, audioPath: audioPath, baseUrl: baseUrl, mode: 'manual', from: 'leftMenuBall' }); }}> ); } } else { return null; } } else { return null; } } catch (ex) { console.log(ex); return null; } }});// The BeaconList component listens for changes and re-renders the// rows (BeaconView components) in that casevar BeaconList = React.createClass({ mixins:[TimerMixin,EventEmitterMixin], getInitialState: function() { return { dataSource: ds.cloneWithRows([]) }; }, componentDidMount(){ /* this.setInterval(()=> { headState = beaconState[0]; if (!modalState) { openHeadState = headState; } beaconState = _.drop(beaconState); if (headState) { let user = RealmRepo.getUser(); //in state if (headState.state == 1) { //init if (lastBeaconId == "") { if (History.lastPlayBeaconId != headState.beaconId) { this.stopSound(); modalState = true; Actions.detail(); this.eventEmitter('emit','refreshDetail',openHeadState); if (user) { RealmRepo.addLog(user.userId, headState.beaconId, '0', headState.extag, ()=> {}); } console.log('open', headState.beaconId); lastBeaconId = headState.beaconId; History.lastPlayBeaconId = lastBeaconId; } } else { if (headState.beaconId != lastBeaconId) { //other beacon in //close first modalState = false; this.eventEmitter('emit', 'detailClose'); if(user) { RealmRepo.addLog(user.userId, lastBeaconId, '1', headState.extag, ()=> {}); } console.log('close', lastBeaconId); lastBeaconId = ""; if (History.lastPlayBeaconId != headState.beaconId) { this.setTimeout(()=> { //then open this.stopSound(); modalState = true; Actions.detail(); this.eventEmitter('emit','refreshDetail',openHeadState); if (user) { RealmRepo.addLog(user.userId, headState.beaconId, '0', headState.extag, ()=> {}); } console.log('open', headState.beaconId); lastBeaconId = headState.beaconId; }, 100); History.lastPlayBeaconId = lastBeaconId; } } else { //the same beacon then keep the state(do nothing) } } } else { //out state if (lastBeaconId == headState.beaconId) { //the same beacon then close modalState = false; this.eventEmitter('emit', 'detailClose'); if(user) { RealmRepo.addLog(user.userId, headState.beaconId, '1', headState.extag, ()=> {}); } console.log('close', lastBeaconId); lastBeaconId = "" } else { //do nothing } } } }, 500);*/ }, log:function(user,state) { //state out-1,in-0 if(user){ if(History.playingId) { RealmRepo.addLog(user.userId, History.playingId, state, History.lastAccessExTag, ()=> {}); //console.log(user.userId,History.playingId,state,History.lastAccessExTag); } } }, triggerPlay:function(major,minor) { if (orderState == null) { orderState = { major: major, minor: minor, createTime: new Date().getTime() }; } else { if (orderState.major == major && orderState.minor == minor) { var now = new Date().getTime(); var duration = now - orderState.createTime; if (duration >= 3000) { if (History.playingId != major + '-' + minor) { let beacon = RealmRepo.getBeaconInfo(major, minor); if (beacon) { let content = beacon.triggercontent[0].content; let audio = beacon.triggercontent[1]; if (content) { let imageUri = RNFS.DocumentDirectoryPath + content.clientpath + content.filename; if (imageUri) { var desc, baseUrl, audioPath, placeHolder; var refImageId = content.contentid; var refAudioId = -1; var exTag = beacon.extag; placeHolder = '{' + content.clientpath + content.filename + '}'; baseUrl = RNFS.DocumentDirectoryPath + content.clientpath; desc = content["description_" + RealmRepo.Locale().displayLang].replace(placeHolder, content.filename); if (audio) { let audioContent = audio.content; if (audioContent) { refAudioId = audioContent.contentid; audioPath = RNFS.DocumentDirectoryPath + audioContent.clientpath + audioContent.filename.replace(".mp3", `_${RealmRepo.Locale().voiceLang}.mp3`); } /* if (audioPath) { this.stopSound(); this.playSound(audioPath); }*/ Actions.detail(); this.eventEmitter('emit', 'refreshDetail', { extag: exTag, refImageId: refImageId, refAudioId: refAudioId, desc: desc, audioPath: audioPath, baseUrl: baseUrl, mode: 'auto', from: 'leftMenuBall' }); } } } } //out let user = RealmRepo.getUser(); this.log(user, 1); //current History.playingId = major + '-' + minor; //in this.log(user, 0); } } } else { orderState = { major: major, minor: minor, createTime: new Date().getTime() }; } } }, componentWillMount: function() { this.eventEmitter('on', 'beaconCountChanged', (orderList)=> { this.setTimeout(()=> { if (orderList) { this.setState({ dataSource: ds.cloneWithRows(orderList) }); if (orderList.length > 0) { this.triggerPlay(orderList[0].major, orderList[0].minor); } else { //this.stopSound(); let user = RealmRepo.getUser(); //out this.log(user,1); //History.playingId = null; } } else { this.setState({ dataSource: ds.cloneWithRows([]) }); } }, 500); }); this.eventEmitter('on', 'drawerOpenFromBallView', ()=> { this.setTimeout(()=> { //this.stopSound(); let user = RealmRepo.getUser(); //out this.log(user,1); History.playingId = null; }, 1000); }); this.eventEmitter('on', 'action', (param)=> { if (param == 'home') { this.setTimeout(()=> { //this.stopSound(); let user = RealmRepo.getUser(); //out this.log(user,1); History.playingId = null; }, 1000); } }); }, playSound:function(audioPath) { s = new Sound(audioPath, null, (e) => { if (e) { console.log('error', e); } else { RNS.headsetDeviceAvailable((v)=> { let user = RealmRepo.getUser(); if (user) { if (user.autoPlay == 1) { if (user.earphonePlay == 1) { if (v) { if (s && s.isLoaded()) { s.setPan(0); s.play(); } } } else { if (s && s.isLoaded()) { s.setPan(0); s.play(); } } } } }); } }); }, stopSound:function() { if (s && s.isLoaded()) { s.stop(); s.release(); } }, renderRow: function(rowData,sectionID,rowID) { return{ /* */} { /*{title ? ( */}{title} ) : null }}, renderHeader:function() { var title = null; let exMaster = (History.lastAccessExTag == '') ? null : RealmRepo.getExMaster(History.lastAccessExTag); if (exMaster) { let locale = RealmRepo.Locale().displayLang; title = exMaster["title_" + locale]; var trimLength = 25;//en or pt if (locale == 'cn' || locale == 'tw') { trimLength = 15;//cn or tw } if (title.length > trimLength) { title = title.slice(0, trimLength).concat('...'); } } return title ? ( ) : null; }, render: function() { return ( {title} ); }});var styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'flex-start', backgroundColor: '#698686' }, headerView:{ height:50, justifyContent: 'flex-start', alignItems: 'center', width:deviceScreen.width }, headerText:{ fontSize: 25, color:'white', textAlign:'center' }, headline: { fontSize: 20, paddingTop: 20 }, row: { flexDirection: 'row', width:deviceScreen.width, padding:5 }, imageView: { borderRadius: 0, overflow: 'hidden' }, descView: { alignItems: 'center', height:36, paddingLeft:2 }, descText: { fontFamily:'Arial-BoldMT', color:'white' }, smallText: { fontSize: 11 }, modal: { justifyContent: 'flex-start', alignItems: 'center', height: deviceScreen.height, width: deviceScreen.width }});module.exports = BeaconList;
Ref:
Ref: