29 | * Also the setting of absolute offsets (similar to translationX/Y), rather than additive
30 | * offsets.
31 | */
32 | public class ViewOffsetHelper {
33 |
34 | private final View mView;
35 |
36 | private int mLayoutTop;
37 | private int mLayoutLeft;
38 | private int mOffsetTop;
39 | private int mOffsetLeft;
40 |
41 | public ViewOffsetHelper(View view) {
42 | mView = view;
43 | }
44 |
45 | public void onViewLayout() {
46 | // Now grab the intended top
47 | mLayoutTop = mView.getTop();
48 | mLayoutLeft = mView.getLeft();
49 |
50 | // And offset it as needed
51 | updateOffsets();
52 | }
53 |
54 | private void updateOffsets() {
55 | ViewCompat.offsetTopAndBottom(mView, mOffsetTop - (mView.getTop() - mLayoutTop));
56 | ViewCompat.offsetLeftAndRight(mView, mOffsetLeft - (mView.getLeft() - mLayoutLeft));
57 |
58 | // Manually invalidate the view and parent to make sure we get drawn pre-M
59 | if (Build.VERSION.SDK_INT < 23) {
60 | tickleInvalidationFlag(mView);
61 | final ViewParent vp = mView.getParent();
62 | if (vp instanceof View) {
63 | tickleInvalidationFlag((View) vp);
64 | }
65 | }
66 | }
67 |
68 | private static void tickleInvalidationFlag(View view) {
69 | final float x = ViewCompat.getTranslationX(view);
70 | ViewCompat.setTranslationY(view, x + 1);
71 | ViewCompat.setTranslationY(view, x);
72 | }
73 |
74 | /**
75 | * Set the top and bottom offset for this {@link ViewOffsetHelper}'s view.
76 | *
77 | * @param offset the offset in px.
78 | * @return true if the offset has changed
79 | */
80 | public boolean setTopAndBottomOffset(int offset) {
81 | if (mOffsetTop != offset) {
82 | mOffsetTop = offset;
83 | updateOffsets();
84 | return true;
85 | }
86 | return false;
87 | }
88 |
89 | /**
90 | * Set the left and right offset for this {@link ViewOffsetHelper}'s view.
91 | *
92 | * @param offset the offset in px.
93 | * @return true if the offset has changed
94 | */
95 | public boolean setLeftAndRightOffset(int offset) {
96 | if (mOffsetLeft != offset) {
97 | mOffsetLeft = offset;
98 | updateOffsets();
99 | return true;
100 | }
101 | return false;
102 | }
103 |
104 | public int getTopAndBottomOffset() {
105 | return mOffsetTop;
106 | }
107 |
108 | public int getLeftAndRightOffset() {
109 | return mOffsetLeft;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/picker/DateFormatUtils.java:
--------------------------------------------------------------------------------
1 | package com.tr4android.support.extension.picker;
2 |
3 | import android.os.Build;
4 | import android.text.format.DateFormat;
5 | import android.text.format.DateUtils;
6 |
7 | import java.text.SimpleDateFormat;
8 | import java.util.Calendar;
9 | import java.util.Locale;
10 |
11 | public class DateFormatUtils {
12 |
13 | public static String getBestDateTimePattern(Locale locale, String skeleton) {
14 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
15 | return DateFormat.getBestDateTimePattern(locale, skeleton);
16 | } else {
17 | // Try to improve the skeleton on older devices
18 | if (skeleton.equals("EMMMd")) return "E, MMM d";
19 | if (skeleton.equals("MMMMy")) return "MMMM yyyy";
20 | if (skeleton.equals("Hm")) return "H:m";
21 | if (skeleton.equals("hm")) return "h:m";
22 | return skeleton;
23 | }
24 | }
25 |
26 | public static String formatDayOfWeek(SimpleDateFormat formatter, Calendar calendar) {
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
28 | return formatter.format(calendar.getTime());
29 | } else {
30 | // Use DateUtils on older devices (Saturday = 7)
31 | int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
32 | return DateUtils.getDayOfWeekString((dayOfWeek == 0) ? 7 : dayOfWeek, DateUtils.LENGTH_SHORTEST);
33 | }
34 | }
35 |
36 | public static String format(SimpleDateFormat formatter, Calendar calendar) {
37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
38 | return formatter.format(calendar.getTime());
39 | } else {
40 | return DateFormat.format(formatter.toLocalizedPattern(), calendar).toString();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/picker/MathUtils.java:
--------------------------------------------------------------------------------
1 | package com.tr4android.support.extension.picker;
2 |
3 | public class MathUtils {
4 |
5 | public static float constrain(float amount, float low, float high) {
6 | return amount < low ? low : (amount > high ? high : amount);
7 | }
8 |
9 | public static int constrain(int amount, int low, int high) {
10 | return amount < low ? low : (amount > high ? high : amount);
11 | }
12 |
13 | public static long constrain(long amount, long low, long high) {
14 | return amount < low ? low : (amount > high ? high : amount);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/picker/date/DayPickerViewPager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tr4android.support.extension.picker.date;
18 |
19 | import android.content.Context;
20 | import android.support.v4.view.ViewCompat;
21 | import android.util.AttributeSet;
22 | import android.view.View;
23 |
24 | import com.tr4android.support.extension.widget.ViewPager;
25 |
26 | import java.util.ArrayList;
27 |
28 | /**
29 | * This displays a list of months in a calendar format with selectable days.
30 | */
31 | class DayPickerViewPager extends ViewPager {
32 | private final ArrayList
42 | * NOTE: This only works starting with API level 14 and comes with a small performance penalty.
43 | * Only use if you have to and cache the result if you need it later.
44 | *
45 | * @param typeface1 The first typeface to be compared.
46 | * @param typeface2 The second typeface to be compared.
47 | * @return True if the typefaces are the same. False otherwise.
48 | * @since 0.1.1
49 | * @deprecated
50 | */
51 | @Deprecated
52 | @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
53 | public static boolean sameAs(Typeface typeface1, Typeface typeface2) {
54 | // Handle null as param.
55 | if (typeface1 == null) {
56 | return typeface2 == null;
57 | } else if (typeface2 == null) {
58 | return false; //result of typeface1 == null
59 | }
60 |
61 | // Check if the letters of the English alphabet of the typefaces are the same.
62 | Paint paint = new Paint();
63 | paint.setTypeface(typeface1);
64 | Rect bounds = new Rect();
65 | paint.getTextBounds(TEXT, 0, TEXT.length(), bounds);
66 | Bitmap bitmap1 = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ALPHA_8);
67 | Canvas canvas = new Canvas(bitmap1);
68 | canvas.drawText(TEXT, 0, 0, paint);
69 |
70 | paint.setTypeface(typeface2);
71 | paint.getTextBounds(TEXT, 0, TEXT.length(), bounds);
72 | Bitmap bitmap2 = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ALPHA_8);
73 | canvas.setBitmap(bitmap2);
74 | canvas.drawText(TEXT, 0, 0, paint);
75 |
76 | return bitmap1.sameAs(bitmap2);
77 | }
78 | }
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/utils/ThemeUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tr4android.support.extension.utils;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 |
22 | public class ThemeUtils {
23 | private static final int[] TEMP_ARRAY = new int[1];
24 |
25 | public static int getThemeAttrColor(Context context, int attr) {
26 | TEMP_ARRAY[0] = attr;
27 | TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
28 | try {
29 | return a.getColor(0, 0);
30 | } finally {
31 | a.recycle();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/utils/ViewCompatUtils.java:
--------------------------------------------------------------------------------
1 | package com.tr4android.support.extension.utils;
2 |
3 | import android.graphics.drawable.Drawable;
4 | import android.os.Build;
5 | import android.support.v4.view.ViewCompat;
6 | import android.view.View;
7 | import android.widget.RelativeLayout;
8 | import android.widget.TextView;
9 |
10 | public class ViewCompatUtils {
11 | public static int getPaddingStart(View view) {
12 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
13 | return view.getPaddingStart();
14 | } else {
15 | return view.getPaddingLeft();
16 | }
17 | }
18 |
19 | public static int getPaddingEnd(View view) {
20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
21 | return view.getPaddingEnd();
22 | } else {
23 | return view.getPaddingRight();
24 | }
25 | }
26 |
27 | public static void setBackground(View view, Drawable drawable) {
28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
29 | view.setBackground(drawable);
30 | } else {
31 | view.setBackgroundDrawable(drawable);
32 | }
33 | }
34 |
35 | public static void setTextAppearance(TextView view, int textAppearanceResId) {
36 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
37 | view.setTextAppearance(textAppearanceResId);
38 | } else {
39 | view.setTextAppearance(view.getContext(), textAppearanceResId);
40 | }
41 | }
42 |
43 | public static void announceForAccessibility(View view, CharSequence text) {
44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
45 | view.announceForAccessibility(text);
46 | } // No-op on versions prior to Jellybean
47 | }
48 |
49 | public static boolean isLayoutRtl(View view) {
50 | return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL;
51 | }
52 |
53 | public static int getRule(RelativeLayout.LayoutParams params, int verb) {
54 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
55 | return params.getRule(verb);
56 | } else {
57 | return params.getRules()[verb];
58 | }
59 | }
60 |
61 | public static void removeRule(RelativeLayout.LayoutParams params, int verb) {
62 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
63 | params.removeRule(verb);
64 | } else {
65 | params.addRule(verb, 0);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/widget/ViewGroupUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tr4android.support.extension.widget;
18 |
19 | import android.graphics.Rect;
20 | import android.os.Build;
21 | import android.view.View;
22 | import android.view.ViewGroup;
23 |
24 | class ViewGroupUtils {
25 |
26 | private interface ViewGroupUtilsImpl {
27 | void offsetDescendantRect(ViewGroup parent, View child, Rect rect);
28 | }
29 |
30 | private static class ViewGroupUtilsImplBase implements ViewGroupUtilsImpl {
31 | @Override
32 | public void offsetDescendantRect(ViewGroup parent, View child, Rect rect) {
33 | parent.offsetDescendantRectToMyCoords(child, rect);
34 | }
35 | }
36 |
37 | private static class ViewGroupUtilsImplHoneycomb implements ViewGroupUtilsImpl {
38 | @Override
39 | public void offsetDescendantRect(ViewGroup parent, View child, Rect rect) {
40 | ViewGroupUtilsHoneycomb.offsetDescendantRect(parent, child, rect);
41 | }
42 | }
43 |
44 | private static final ViewGroupUtilsImpl IMPL;
45 |
46 | static {
47 | final int version = Build.VERSION.SDK_INT;
48 | if (version >= 11) {
49 | IMPL = new ViewGroupUtilsImplHoneycomb();
50 | } else {
51 | IMPL = new ViewGroupUtilsImplBase();
52 | }
53 | }
54 |
55 | /**
56 | * This is a port of the common
57 | * {@link ViewGroup#offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect)}
58 | * from the framework, but adapted to take transformations into account. The result
59 | * will be the bounding rect of the real transformed rect.
60 | *
61 | * @param descendant view defining the original coordinate system of rect
62 | * @param rect (in/out) the rect to offset from descendant to this view's coordinate system
63 | */
64 | static void offsetDescendantRect(ViewGroup parent, View descendant, Rect rect) {
65 | IMPL.offsetDescendantRect(parent, descendant, rect);
66 | }
67 |
68 | /**
69 | * Retrieve the transformed bounding rect of an arbitrary descendant view.
70 | * This does not need to be a direct child.
71 | *
72 | * @param descendant descendant view to reference
73 | * @param out rect to set to the bounds of the descendant view
74 | */
75 | static void getDescendantRect(ViewGroup parent, View descendant, Rect out) {
76 | out.set(0, 0, descendant.getWidth(), descendant.getHeight());
77 | offsetDescendantRect(parent, descendant, out);
78 | }
79 |
80 | }
--------------------------------------------------------------------------------
/appcompat-extension/src/main/java/com/tr4android/support/extension/widget/ViewGroupUtilsHoneycomb.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tr4android.support.extension.widget;
18 |
19 | import android.annotation.TargetApi;
20 | import android.graphics.Matrix;
21 | import android.graphics.Rect;
22 | import android.graphics.RectF;
23 | import android.os.Build;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.view.ViewParent;
27 |
28 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
29 | class ViewGroupUtilsHoneycomb {
30 | private static final ThreadLocal