Skip to content

Commit

Permalink
Cross-platform tint color support (#226)
Browse files Browse the repository at this point in the history
* tint color support (#2)

* add image color support

* added tintcolor support for android

* changed prop to be named tintColor for consistency

* fixed bug where tint color would not work on ios 10

* removed file accidentally added back in by merging master

* updated readme, fixed prop warning

* re-formatted with new rules
  • Loading branch information
millibeckers authored and DylanVann committed May 3, 2019
1 parent 161ba99 commit ad97e47
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 8 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ A React Native style. Supports using `borderRadius`.
If true will fallback to using `Image`.
In this case the image will still be styled and laid out the same way as `FastImage`.

---

### `tintColor?: number | string`

If supplied, changes the color of all the non-transparent pixels to the given color.

## Static Methods

### `FastImage.preload: (source[]) => void`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.Activity;
import android.content.Context;
import android.graphics.PorterDuff;
import android.os.Build;

import com.bumptech.glide.Glide;
Expand Down Expand Up @@ -108,6 +109,15 @@ public void setSrc(FastImageViewWithUrl view, @Nullable ReadableMap source) {
}
}

@ReactProp(name = "tintColor", customType = "Color")
public void setTintColor(FastImageViewWithUrl view, @Nullable Integer color) {
if (color == null) {
view.clearColorFilter();
} else {
view.setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}

@ReactProp(name = "resizeMode")
public void setResizeMode(FastImageViewWithUrl view, String resizeMode) {
final FastImageViewWithUrl.ScaleType scaleType = FastImageViewConverter.getScaleType(resizeMode);
Expand Down
1 change: 1 addition & 0 deletions ios/FastImage/FFFastImageView.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
@property (nonatomic, copy) RCTDirectEventBlock onFastImageLoadEnd;
@property (nonatomic, assign) RCTResizeMode resizeMode;
@property (nonatomic, strong) FFFastImageSource *source;
@property (nonatomic, strong) UIColor *imageColor;

@end

36 changes: 30 additions & 6 deletions ios/FastImage/FFFastImageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ - (void)setOnFastImageLoadStart:(RCTDirectEventBlock)onFastImageLoadStart {
}
}

- (void)setImageColor:(UIColor *)imageColor {
if (imageColor != nil) {
_imageColor = imageColor;
super.image = [self makeImage:super.image withTint:self.imageColor];
}
}

- (UIImage*)makeImage:(UIImage *)image withTint:(UIColor *)color {
UIImage *newImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIGraphicsBeginImageContextWithOptions(image.size, NO, newImage.scale);
[color set];
[newImage drawInRect:CGRectMake(0, 0, image.size.width, newImage.size.height)];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

- (void)setImage:(UIImage *)image {
if (self.imageColor != nil) {
super.image = [self makeImage:image withTint:self.imageColor];
} else {
super.image = image;
}
}

- (void)sendOnLoad:(UIImage *)image {
self.onLoadEvent = @{
@"width":[NSNumber numberWithDouble:image.size.width],
Expand All @@ -69,10 +94,11 @@ - (void)sendOnLoad:(UIImage *)image {
}
}


- (void)setSource:(FFFastImageSource *)source {
if (_source != source) {
_source = source;

// Load base64 images.
NSString* url = [_source.url absoluteString];
if (url && [url hasPrefix:@"data:image"]) {
Expand All @@ -98,12 +124,12 @@ - (void)setSource:(FFFastImageSource *)source {
}
return;
}

// Set headers.
[_source.headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString* header, BOOL *stop) {
[[SDWebImageDownloader sharedDownloader] setValue:header forHTTPHeaderField:key];
}];

// Set priority.
SDWebImageOptions options = SDWebImageRetryFailed;
switch (_source.priority) {
Expand All @@ -117,7 +143,7 @@ - (void)setSource:(FFFastImageSource *)source {
options |= SDWebImageHighPriority;
break;
}

switch (_source.cacheControl) {
case FFFCacheControlWeb:
options |= SDWebImageRefreshCached;
Expand All @@ -128,7 +154,6 @@ - (void)setSource:(FFFastImageSource *)source {
case FFFCacheControlImmutable:
break;
}

if (self.onFastImageLoadStart) {
self.onFastImageLoadStart(@{});
self.hasSentOnLoadStart = YES;
Expand Down Expand Up @@ -177,4 +202,3 @@ - (void)downloadImage:(FFFastImageSource *) source options:(SDWebImageOptions) o
}

@end

5 changes: 3 additions & 2 deletions ios/FastImage/FFFastImageViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ - (FFFastImageView*)view {
RCT_EXPORT_VIEW_PROPERTY(onFastImageError, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onFastImageLoad, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onFastImageLoadEnd, RCTDirectEventBlock)
RCT_REMAP_VIEW_PROPERTY(tintColor, imageColor, UIColor)

RCT_EXPORT_METHOD(preload:(nonnull NSArray<FFFastImageSource *> *)sources)
{
NSMutableArray *urls = [NSMutableArray arrayWithCapacity:sources.count];

[sources enumerateObjectsUsingBlock:^(FFFastImageSource * _Nonnull source, NSUInteger idx, BOOL * _Nonnull stop) {
[source.headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString* header, BOOL *stop) {
[[SDWebImageDownloader sharedDownloader] setValue:header forHTTPHeaderField:key];
}];
[urls setObject:source.url atIndexedSubscript:idx];
}];

[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls];
}

Expand Down
2 changes: 2 additions & 0 deletions react-native-fast-image-example/src/FastImageExamples.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FeatureText from './FeatureText'
import ProgressExample from './ProgressExample'
import PreloadExample from './PreloadExample'
import ResizeModeExample from './ResizeModeExample'
import TintColorExample from './TintColorExample'
import LocalImagesExample from './LocalImagesExample'
import StatusBarUnderlay, { STATUS_BAR_HEIGHT } from './StatusBarUnderlay'
import AutoSizeExample from './AutoSizeExample'
Expand All @@ -35,6 +36,7 @@ const FastImageExample = () => (
<ProgressExample />
<PreloadExample />
<ResizeModeExample />
<TintColorExample />
<LocalImagesExample />
<AutoSizeExample />
</View>
Expand Down
62 changes: 62 additions & 0 deletions react-native-fast-image-example/src/TintColorExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react'
import { PixelRatio, StyleSheet, View } from 'react-native'
import withCacheBust from './withCacheBust'
import FastImage from 'react-native-fast-image'
import Section from './Section'
import SectionFlex from './SectionFlex'
import FeatureText from './FeatureText'

const getImageUrl = (id, width, height) =>
`https://source.unsplash.com/${id}/${width}x${height}`
const IMAGE_SIZE = 1024
const IMAGE_SIZE_PX = PixelRatio.getPixelSizeForLayoutSize(IMAGE_SIZE)
const IMAGE_URLS = [
getImageUrl('x58soEovG_M', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('yPI7myL5eWY', IMAGE_SIZE_PX, IMAGE_SIZE_PX),
getImageUrl('S7VCcp6KCKE', IMAGE_SIZE, IMAGE_SIZE),
]

const TintColorExample = ({ onPressReload, bust }) => (
<View>
<Section>
<FeatureText text="Images with tint color" />
</Section>
<SectionFlex onPress={onPressReload}>
<FastImage
style={styles.image}
tintColor={'green'}
source={{
uri: IMAGE_URLS[0] + bust,
priority: FastImage.priority.low,
}}
/>
<FastImage
style={styles.image}
tintColor={'#9324c3'}
source={{
uri: IMAGE_URLS[1],
priority: FastImage.priority.normal,
}}
/>
<FastImage
style={styles.image}
tintColor={'rgba(0,0,0,0.5)'}
source={{
uri: IMAGE_URLS[2] + bust,
priority: FastImage.priority.high,
}}
/>
</SectionFlex>
</View>
)

const styles = StyleSheet.create({
image: {
flex: 1,
height: 100,
backgroundColor: '#ddd',
margin: 10,
},
})

export default withCacheBust(TintColorExample)
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const FastImageViewNativeModule = NativeModules.FastImageView

function FastImageBase({
source,
tintColor,
onLoadStart,
onProgress,
onLoad,
Expand All @@ -31,6 +32,7 @@ function FastImageBase({
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<Image
{...props}
tintColor={tintColor}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onLoadStart={onLoadStart}
Expand All @@ -48,6 +50,7 @@ function FastImageBase({
<View style={[styles.imageContainer, style]} ref={forwardedRef}>
<FastImageView
{...props}
tintColor={tintColor}
style={StyleSheet.absoluteFill}
source={resolvedSource}
onFastImageLoadStart={onLoadStart}
Expand Down Expand Up @@ -118,6 +121,7 @@ const FastImageSourcePropType = PropTypes.shape({
FastImage.propTypes = {
...ViewPropTypes,
source: PropTypes.oneOfType([FastImageSourcePropType, PropTypes.number]),
tintColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
onLoadStart: PropTypes.func,
onProgress: PropTypes.func,
onLoad: PropTypes.func,
Expand Down

0 comments on commit ad97e47

Please sign in to comment.