Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-platform tint color support #226

Merged
merged 16 commits into from
May 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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