/* * Copyright 2017-present The Material Motion Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.material.motion.properties; import android.graphics.Color; import android.graphics.PointF; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.IdRes; import android.support.annotation.VisibleForTesting; import android.util.Property; import android.view.View; import com.google.android.material.motion.R; import com.google.android.material.motion.springs.PointFTypeVectorizer; import com.google.android.material.motion.springs.TypeVectorizer; public final class ViewProperties { @VisibleForTesting public ViewProperties() { throw new UnsupportedOperationException(); } public static final Property<View, PointF> TRANSLATION = new DerivativeProperty<>( PointF.class, "translation", new PointFTypeVectorizer(), View.TRANSLATION_X, View.TRANSLATION_Y); public static final Property<View, PointF> CENTER = new DerivativeProperty<View, PointF>( PointF.class, "center", new PointFTypeVectorizer(), View.X, View.Y) { @Override public float setterTransformation(View object, float value) { return value - object.getWidth() / 2f; } @Override public float getterTransformation(View object, float value) { return value + object.getWidth() / 2f; } }; public static final Property<View, PointF> SCALE = new DerivativeProperty<>( PointF.class, "scale", new PointFTypeVectorizer(), View.SCALE_X, View.SCALE_Y); public static final Property<View, PointF> PIVOT = new Property<View, PointF>(PointF.class, "pivot") { @Override public void set(View object, PointF value) { object.setPivotX(value.x); object.setPivotY(value.y); } @Override public PointF get(View object) { PointF pointF = new PointF(); pointF.x = object.getPivotX(); pointF.y = object.getPivotY(); return pointF; } }; public static final Property<View, Float> SCROLL_X = new Property<View, Float>(Float.class, "scrollX") { @Override public Float get(View object) { return (float) object.getScrollX(); } @Override public void set(View object, Float value) { object.setScrollX((int) (float) value); } }; public static final Property<View, Float> SCROLL_Y = new Property<View, Float>(Float.class, "scrollY") { @Override public Float get(View object) { return (float) object.getScrollY(); } @Override public void set(View object, Float value) { object.setScrollY((int) (float) value); } }; public static final Property<View, PointF> ANCHOR_POINT_ADJUSTMENT = new TagProperty<PointF>( PointF.class, "anchor_point_adjustment", R.id.gesture_anchor_point_adjustment_tag, new PointF(0f, 0f)) { @Override public void set(View object, PointF adjustment) { super.set(object, adjustment); object.setTranslationX(object.getTranslationX() + adjustment.x); object.setTranslationY(object.getTranslationY() + adjustment.y); } @Override public PointF get(View object) { return super.get(object); } }; public static final Property<View, Integer> BACKGROUND_COLOR = new Property<View, Integer>(Integer.class, "background_color") { @Override public void set(View object, Integer value) { object.setBackgroundColor(value); } @Override public Integer get(View object) { Drawable background = object.getBackground(); if (background instanceof ColorDrawable) { return ((ColorDrawable) background).getColor(); } return Color.TRANSPARENT; } }; private static class TagProperty<T> extends Property<View, T> { private final int id; private final T initialValue; public TagProperty(Class<T> type, String name, @IdRes int id, T initialValue) { super(type, name); this.id = id; this.initialValue = initialValue; } @Override public void set(View object, T value) { object.setTag(id, value); } @Override public T get(View object) { Object value = object.getTag(id); if (value == null) { value = initialValue; } //noinspection unchecked return (T) value; } } public static class DerivativeProperty<O, T> extends Property<O, T> { public final TypeVectorizer<T> vectorizer; public final Property<O, Float>[] properties; private final float[] vector; @SafeVarargs public DerivativeProperty( Class<T> type, String name, TypeVectorizer<T> vectorizer, Property<O, Float>... properties) { super(type, name); this.vectorizer = vectorizer; this.properties = properties; this.vector = new float[vectorizer.getVectorLength()]; } @Override public final void set(O object, T value) { vectorizer.vectorize(value, vector); for (int i = 0; i < properties.length; i++) { properties[i].set(object, setterTransformation(object, vector[i])); } } @Override public final T get(O object) { for (int i = 0; i < properties.length; i++) { vector[i] = getterTransformation(object, properties[i].get(object)); } return vectorizer.compose(vector); } public float setterTransformation(O object, float value) { return value; } public float getterTransformation(O object, float value) { return value; } } }