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

[TIMOB-19578] Material design custom animations - touch feedback #7317

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -838,6 +838,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 @@ -66,7 +66,10 @@
// others
"focusable", "touchEnabled", "visible", "enabled", "opacity",
"softKeyboardOnFocus", "transform", "elevation", "touchTestId",
"translationX", "translationY", "translationZ"
"translationX", "translationY", "translationZ",

// touch feedback properties
TiC.PROPERTY_TOUCH_FEEDBACK, TiC.PROPERTY_TOUCH_FEEDBACK_COLOR
})
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 @@ -760,6 +766,7 @@ 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.startsWith(TiC.PROPERTY_BACKGROUND_PREFIX)
|| key.startsWith(TiC.PROPERTY_BORDER_PREFIX)) {
// Update first before querying.
Expand All @@ -774,7 +781,10 @@ 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 @@ -786,10 +796,16 @@ 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 @@ -929,17 +945,23 @@ 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 @@ -1032,6 +1054,39 @@ private void applyCustomBackground(boolean reuseCurrentDrawable)
nativeView.setBackgroundDrawable(background);
}
}

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

/**
* Applies touch feedback. Should check canApplyTouchFeedback() before calling this.
* @param bgColor The background color of the view.
* @param rippleColor The ripple color.
*/
private void applyTouchFeedback(@NonNull Integer bgColor, @Nullable Integer rippleColor) {
Context appContext = TiApplication.getInstance();
if (rippleColor == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like some indentation issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed indentation issue. Please review.

TypedValue resolvedAttr = new TypedValue();
if(appContext.getTheme().resolveAttribute(android.R.attr.colorControlHighlight, resolvedAttr, true)) {
rippleColor = appContext.getResources().getColor(resolvedAttr.resourceId);
} else {
throw new RuntimeException("android.R.attr.colorControlHighlight cannot be resolved into Drawable");
}
}
RippleDrawable rippleDrawable = new RippleDrawable(ColorStateList.valueOf(rippleColor), new ColorDrawable(bgColor), null);
nativeView.setBackground(rippleDrawable);
}

public void onFocusChange(final View v, boolean hasFocus)
{
Expand Down
18 changes: 18 additions & 0 deletions apidoc/Titanium/UI/View.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,23 @@ properties:
default: 0


- 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]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing since: "5.2.0"



- name: touchFeedbackColor
summary: Optional touch feedback ripple color.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should mention that this property does nothing unless touchFeedback is true

type: String
default: Theme provided color.
platforms: [android]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missin since: "5.2.0"



- name: bottom
summary: View's bottom position, in platform-specific units.
description: |
Expand All @@ -1074,6 +1091,7 @@ properties:
represent the view's calculated position.
type: [Number,String]
default: undefined


- name: center
summary: View's center position, in the parent view's coordinates.
Expand Down