Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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
9 changes: 9 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:8.8.2'
Expand All @@ -24,6 +25,14 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}

// Ensure BlurView v2 is used if other modules request a different version
configurations.all { cfg ->
resolutionStrategy {
force 'com.github.Dimezis:BlurView:version-2.0.5'
Comment thread
hansemannn marked this conversation as resolved.
Outdated
}
}

// Load plugin used to enforce our Java coding style guidelines.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Titanium SDK
* Copyright TiDev, Inc. 04/07/2022-Present
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
package ti.modules.titanium.ui;

import android.app.Activity;

import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.view.TiUIView;

import ti.modules.titanium.ui.widget.TiUIBlurView;

@Kroll.proxy(creatableInModule = UIModule.class)
public class BlurViewProxy extends TiViewProxy
{
public BlurViewProxy()
{
super();
}

@Override
public TiUIView createView(Activity activity)
{
return new TiUIBlurView(this);
}

@Override
public String getApiName()
{
return "Ti.UI.BlurView";
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ public class UIModule extends KrollModule implements TiApplication.Configuration
@Kroll.constant
public static final int BUTTON_STYLE_OPTION_NEUTRAL = 6;

// BlurView styles (cross-platform constants)
@Kroll.constant
public static final int BLUR_EFFECT_STYLE_EXTRA_LIGHT = 0;
@Kroll.constant
public static final int BLUR_EFFECT_STYLE_LIGHT = 1;
@Kroll.constant
public static final int BLUR_EFFECT_STYLE_DARK = 2;

@Kroll.constant
public static final int DATE_PICKER_STYLE_AUTOMATIC = 1;
@Kroll.constant
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/**
* Titanium SDK
* Copyright TiDev, Inc. 04/07/2022-Present
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
package ti.modules.titanium.ui.widget;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.view.TiCompositeLayout;
import org.appcelerator.titanium.view.TiUIView;

import androidx.annotation.Nullable;

import eightbitlab.com.blurview.BlurView;
import ti.modules.titanium.ui.UIModule;

public class TiUIBlurView extends TiUIView
{
private static final String TAG = "TiUIBlurView";

// Custom property keys (Android-only)
private static final String PROPERTY_EFFECT = "effect"; // Number (Ti.UI.BLUR_EFFECT_STYLE_*)
private static final String PROPERTY_BLUR_RADIUS = "blurRadius"; // Number
private static final String PROPERTY_OVERLAY_COLOR = "overlayColor"; // String color

private final BlurView blurView;
private final TiCompositeLayout contentLayout;

// Current config
private float blurRadius = 16f;
private int overlayColor = 0x00FFFFFF; // transparent by default
private int effectStyle = -1; // unset

private class BlurContainer extends FrameLayout
{
final TiCompositeLayout layout;
final BlurView innerBlurView;

BlurContainer()
{
super(proxy.getActivity());

// Determine arrangement from proxy
TiCompositeLayout.LayoutArrangement arrangement = TiCompositeLayout.LayoutArrangement.DEFAULT;
Object layoutValue = proxy.getProperty(TiC.PROPERTY_LAYOUT);
if (TiC.LAYOUT_VERTICAL.equals(layoutValue)) {
arrangement = TiCompositeLayout.LayoutArrangement.VERTICAL;
} else if (TiC.LAYOUT_HORIZONTAL.equals(layoutValue)) {
arrangement = TiCompositeLayout.LayoutArrangement.HORIZONTAL;
}

// Create blur and content layout
innerBlurView = new BlurView(proxy.getActivity());
innerBlurView.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

layout = new TiCompositeLayout(proxy.getActivity(), arrangement, proxy);
layout.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

// Add in order: blur background then content overlay
super.addView(innerBlurView);
super.addView(layout);
}

TiCompositeLayout getLayout()
{
return layout;
}

BlurView getBlurView()
{
return innerBlurView;
}

@Override
public void addView(View child, ViewGroup.LayoutParams params)
{
// Route adds to TiCompositeLayout to ensure correct LayoutParams
layout.addView(child, params);
}
}

public TiUIBlurView(TiViewProxy proxy)
{
super(proxy);

BlurContainer container = new BlurContainer();
this.blurView = container.getBlurView();
this.contentLayout = container.getLayout();

setNativeView(container);
// Defer setup until we know the target (if provided)
setupOrUpdateBlur();
}

@Override
public void processProperties(KrollDict d)
{
super.processProperties(d);

if (d.containsKey(PROPERTY_BLUR_RADIUS)) {
this.blurRadius = TiConvert.toFloat(d, PROPERTY_BLUR_RADIUS, this.blurRadius);
}
if (d.containsKey(PROPERTY_OVERLAY_COLOR)) {
this.overlayColor = TiConvert.toColor(d.get(PROPERTY_OVERLAY_COLOR), proxy.getActivity());
}
if (d.containsKey(PROPERTY_EFFECT)) {
this.effectStyle = TiConvert.toInt(d.get(PROPERTY_EFFECT), -1);
applyEffectPresetIfAny();
}

setupOrUpdateBlur();
}

@Override
public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy)
{
if (Log.isDebugModeEnabled()) {
Log.d(TAG, "Property changed: " + key + ", new: " + newValue, Log.DEBUG_MODE);
}

if (PROPERTY_BLUR_RADIUS.equals(key)) {
this.blurRadius = TiConvert.toFloat(newValue, this.blurRadius);
if (blurView != null) {
blurView.setBlurRadius(this.blurRadius);
}
} else if (PROPERTY_OVERLAY_COLOR.equals(key)) {
this.overlayColor = TiConvert.toColor(newValue, proxy.getActivity());
if (blurView != null) {
blurView.setOverlayColor(this.overlayColor);
}
} else if (PROPERTY_EFFECT.equals(key)) {
this.effectStyle = TiConvert.toInt(newValue, -1);
applyEffectPresetIfAny();
if (blurView != null) {
blurView.setOverlayColor(this.overlayColor);
blurView.setBlurRadius(this.blurRadius);
}
} else {
super.propertyChanged(key, oldValue, newValue, proxy);
}
}

private void setupOrUpdateBlur()
{
if (blurView == null) {
return;
}

Drawable windowBackground = getWindowBackground();
if (windowBackground == null) {
windowBackground = new ColorDrawable(Color.TRANSPARENT);
}

// Legacy API: setup with root content view, using RenderScriptBlur for <31
ViewGroup rootView = getRootContentView();
if (rootView == null) {
return;
}

blurView.setupWith(rootView)
.setFrameClearDrawable(windowBackground)
.setBlurRadius(this.blurRadius)
.setOverlayColor(this.overlayColor);
}

private void applyEffectPresetIfAny()
{
// Map iOS-like styles to Android parameters.
// These constants are defined on Ti.UI.*
// Default values already set on fields.
switch (this.effectStyle) {
case UIModule.BLUR_EFFECT_STYLE_EXTRA_LIGHT:
this.blurRadius = 16f;
this.overlayColor = 0x66FFFFFF; // strongest white tint
break;
case UIModule.BLUR_EFFECT_STYLE_LIGHT:
this.blurRadius = 16f;
this.overlayColor = 0x44FFFFFF; // medium white tint
break;
case UIModule.BLUR_EFFECT_STYLE_DARK:
this.blurRadius = 16f;
this.overlayColor = 0x66000000; // dark tint
break;
default:
// leave custom values as-is when unknown
break;
}
}

@Nullable
private ViewGroup getRootContentView()
{
if (proxy == null || proxy.getActivity() == null || proxy.getActivity().getWindow() == null) {
return null;
}
View decor = proxy.getActivity().getWindow().getDecorView();
View content = decor.findViewById(android.R.id.content);
if (content instanceof ViewGroup) {
return (ViewGroup) content;
}
return null;
}

@Nullable
private Drawable getWindowBackground()
{
if (proxy == null || proxy.getActivity() == null || proxy.getActivity().getWindow() == null) {
return null;
}
return proxy.getActivity().getWindow().getDecorView().getBackground();
}
}
3 changes: 3 additions & 0 deletions android/titanium/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ dependencies {
// Reference all local JAR file dependencies.
implementation fileTree(dir: 'lib', include: ['*.jar'])

// BlurView (Dimezis) v2 via JitPack (no BlurTarget)
implementation 'com.github.Dimezis:BlurView:version-2.0.5'

// CameraX
def camerax_version = '1.4.2'
implementation "androidx.camera:camera-core:$camerax_version"
Expand Down
Loading
Loading