Skip to content

Commit

Permalink
Merge pull request #8446 from garymathews/TIMOB-19578
Browse files Browse the repository at this point in the history
[TIMOB-19578] Material design custom animations and touch feedback
  • Loading branch information
hansemannn committed Sep 29, 2016
2 parents 720d073 + a4bbb45 commit 664f97a
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 17 deletions.
10 changes: 10 additions & 0 deletions android/titanium/src/java/org/appcelerator/titanium/TiC.java
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,16 @@ public class TiC
*/
public static final String PROPERTY_BACKGROUND_SELECTED_IMAGE = "backgroundSelectedImage";

/**
* @module.api
*/
public static final String PROPERTY_TOUCH_FEEDBACK = "touchFeedback";

/**
* @module.api
*/
public static final String PROPERTY_TOUCH_FEEDBACK_COLOR = "touchFeedbackColor";

/**
* @module.api
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"softKeyboardOnFocus", "transform", "elevation", "touchTestId",
"translationX", "translationY", "translationZ", "rotation", "rotationX", "rotationY", "scaleX", "scaleY",

TiC.PROPERTY_TRANSITION_NAME
TiC.PROPERTY_TOUCH_FEEDBACK, TiC.PROPERTY_TOUCH_FEEDBACK_COLOR, TiC.PROPERTY_TRANSITION_NAME
})
public abstract class TiViewProxy extends KrollProxy implements Handler.Callback
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,23 @@
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.KeyEvent;
Expand Down Expand Up @@ -769,6 +775,8 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
} else if (key.startsWith(TiC.PROPERTY_BACKGROUND_PADDING)) {
Log.i(TAG, key + " not yet implemented.");
} else if (key.equals(TiC.PROPERTY_OPACITY)
|| key.equals(TiC.PROPERTY_TOUCH_FEEDBACK_COLOR)
|| key.equals(TiC.PROPERTY_TOUCH_FEEDBACK)
|| key.startsWith(TiC.PROPERTY_BACKGROUND_PREFIX)
|| key.startsWith(TiC.PROPERTY_BORDER_PREFIX)) {
// Update first before querying.
Expand All @@ -783,7 +791,12 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
boolean hasGradient = hasGradient(d);
boolean nativeViewNull = (nativeView == null);

boolean requiresCustomBackground = hasImage || hasRepeat || hasColorState || hasBorder || hasGradient;
boolean requiresCustomBackground = hasImage || hasColorState || hasBorder || hasGradient;

// PROPERTY_BACKGROUND_REPEAT is implicitly passed as false though not used in JS. So check the truth value and proceed.
if (!requiresCustomBackground) {
requiresCustomBackground = requiresCustomBackground && d.optBoolean(TiC.PROPERTY_BACKGROUND_REPEAT, false);
}

if (!requiresCustomBackground) {
if (background != null) {
Expand All @@ -795,10 +808,14 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
if (d.containsKeyAndNotNull(TiC.PROPERTY_BACKGROUND_COLOR)) {
Integer bgColor = TiConvert.toColor(d, TiC.PROPERTY_BACKGROUND_COLOR);
if (!nativeViewNull) {
nativeView.setBackgroundColor(bgColor);
// A bug only on Android 2.3 (TIMOB-14311).
if (Build.VERSION.SDK_INT < TiC.API_LEVEL_HONEYCOMB && proxy.hasProperty(TiC.PROPERTY_OPACITY)) {
setOpacity(TiConvert.toFloat(proxy.getProperty(TiC.PROPERTY_OPACITY), 1f));
if (canApplyTouchFeedback(d)) {
applyTouchFeedback(bgColor, d.containsKey(TiC.PROPERTY_TOUCH_FEEDBACK_COLOR) ? TiConvert.toColor(d, TiC.PROPERTY_TOUCH_FEEDBACK_COLOR) : null);
} else {
nativeView.setBackgroundColor(bgColor);
// A bug only on Android 2.3 (TIMOB-14311).
if (Build.VERSION.SDK_INT < TiC.API_LEVEL_HONEYCOMB && proxy.hasProperty(TiC.PROPERTY_OPACITY)) {
setOpacity(TiConvert.toFloat(proxy.getProperty(TiC.PROPERTY_OPACITY), 1f));
}
}
nativeView.postInvalidate();
}
Expand Down Expand Up @@ -962,17 +979,21 @@ public void processProperties(KrollDict d)
} else if (d.containsKey(TiC.PROPERTY_BACKGROUND_COLOR) && !nativeViewNull) {
bgColor = TiConvert.toColor(d, TiC.PROPERTY_BACKGROUND_COLOR);

// Set the background color on the view directly only
// if there is no border. If a border is present we must
// use the TiBackgroundDrawable.
if (hasBorder(d)) {
if (background == null) {
applyCustomBackground(false);
}
background.setBackgroundColor(bgColor);


if (canApplyTouchFeedback(d)) {
applyTouchFeedback(bgColor, d.containsKey(TiC.PROPERTY_TOUCH_FEEDBACK_COLOR) ? TiConvert.toColor(d, TiC.PROPERTY_TOUCH_FEEDBACK_COLOR) : null);
} else {
nativeView.setBackgroundColor(bgColor);
// Set the background color on the view directly only
// if there is no border. If a border is present we must
// use the TiBackgroundDrawable.
if (hasBorder(d)) {
if (background == null) {
applyCustomBackground(false);
}
background.setBackgroundColor(bgColor);
} else {
nativeView.setBackgroundColor(bgColor);
}
}
}

Expand Down Expand Up @@ -1091,6 +1112,33 @@ private void applyCustomBackground(boolean reuseCurrentDrawable)
}
}

/**
* @param props View's property dictionary
* @return true if touch feedback can be applied.
*/
protected boolean canApplyTouchFeedback(@NonNull KrollDict props) {
return ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) && props.optBoolean(TiC.PROPERTY_TOUCH_FEEDBACK, false) && !hasBorder(props));
}

/**
* Applies touch feedback. Should check canApplyTouchFeedback() before calling this.
* @param backgroundColor The background color of the view.
* @param rippleColor The ripple color.
*/
private void applyTouchFeedback(@NonNull Integer backgroundColor, @Nullable Integer rippleColor) {
if (rippleColor == null) {
Context context = TiApplication.getInstance();
TypedValue attribute = new TypedValue();
if (context.getTheme().resolveAttribute(android.R.attr.colorControlHighlight, attribute, true)) {
rippleColor = context.getResources().getColor(attribute.resourceId);
} else {
throw new RuntimeException("android.R.attr.colorControlHighlight cannot be resolved into Drawable");
}
}
RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(rippleColor), new ColorDrawable(backgroundColor), null);
nativeView.setBackground(rippleDrawable);
}

public void onFocusChange(final View v, boolean hasFocus)
{
if (hasFocus) {
Expand Down
21 changes: 20 additions & 1 deletion apidoc/Titanium/UI/View.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,26 @@ properties:
description: If false, will forward the events to peers.
type: Boolean
default: true


- name: touchFeedback
summary: A material design visual construct that provides an instantaneous visual confirmation of touch point.
description: |
This is an opt-in feature available from Android Lollipop.
Touch feedback is applied only if the backgroundColor is a solid color.
type: Boolean
default: false
platforms: [android]
osver: {android: {min: "5.0"}}
since: "6.1.0"

- name: touchFeedbackColor
summary: Optional touch feedback ripple color. This has no effect unless `touchFeedback` is true.
type: String
default: Theme provided color.
platforms: [android]
osver: {android: {min: "5.0"}}
since: "6.1.0"

- name: transform
summary: Transformation matrix to apply to the view.
description: Android and Mobile Web only support 2DMatrix transforms.
Expand Down

0 comments on commit 664f97a

Please sign in to comment.