diff options
author | Tony Wickham <twickham@google.com> | 2016-05-16 09:54:06 -0700 |
---|---|---|
committer | Tony Wickham <twickham@google.com> | 2016-05-17 18:53:57 -0700 |
commit | f549dab31d0fa3e4d0cf8d6025b20e49aafb2d59 (patch) | |
tree | a10ccc74b4d0ad6f353a0a6853950335156c748b /src/com/android/launcher3/pageindicators/PageIndicatorDots.java | |
parent | 192ae6ca71b0a1401ad44020b631c634a348597e (diff) | |
download | android_packages_apps_Trebuchet-f549dab31d0fa3e4d0cf8d6025b20e49aafb2d59.tar.gz android_packages_apps_Trebuchet-f549dab31d0fa3e4d0cf8d6025b20e49aafb2d59.tar.bz2 android_packages_apps_Trebuchet-f549dab31d0fa3e4d0cf8d6025b20e49aafb2d59.zip |
Add PageIndicator interface and custom PageIndicatorLine view.
- The current PageIndicator has been renamed to PageIndicatorDots
and PageIndicatorMarker has been renamed to PageIndicatorDot.
- PageIndicatorDots and PageIndicatorLine implement PageIndicator.
- PageIndicatorLine uses scroll progress and number of pages to
draw a line of the correct size and position.
- All of these page indicator files are now in a pageindicators package.
Bug: 27227498
Change-Id: I9230d2e0600ce583989bd31d0b0e252b148d15c2
Diffstat (limited to 'src/com/android/launcher3/pageindicators/PageIndicatorDots.java')
-rw-r--r-- | src/com/android/launcher3/pageindicators/PageIndicatorDots.java | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java new file mode 100644 index 000000000..a488f028a --- /dev/null +++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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.android.launcher3.pageindicators; + +import android.animation.LayoutTransition; +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewDebug; +import android.widget.LinearLayout; + +import com.android.launcher3.R; + +import java.util.ArrayList; + +public class PageIndicatorDots extends LinearLayout implements PageIndicator { + @SuppressWarnings("unused") + private static final String TAG = "PageIndicator"; + // Want this to look good? Keep it odd + private static final boolean MODULATE_ALPHA_ENABLED = false; + + private LayoutInflater mLayoutInflater; + private int[] mWindowRange = new int[2]; + private int mMaxWindowSize; + + private ArrayList<PageIndicatorDot> mMarkers = new ArrayList<>(); + @ViewDebug.ExportedProperty(category = "launcher") + private int mActiveMarkerIndex; + + public PageIndicatorDots(Context context) { + this(context, null); + } + + public PageIndicatorDots(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PageIndicatorDots(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.PageIndicatorDots, defStyle, 0); + mMaxWindowSize = a.getInteger(R.styleable.PageIndicatorDots_windowSize, 15); + mWindowRange[0] = 0; + mWindowRange[1] = 0; + mLayoutInflater = LayoutInflater.from(context); + a.recycle(); + + // Set the layout transition properties + LayoutTransition transition = getLayoutTransition(); + transition.setDuration(175); + } + + private void enableLayoutTransitions() { + LayoutTransition transition = getLayoutTransition(); + transition.enableTransitionType(LayoutTransition.APPEARING); + transition.enableTransitionType(LayoutTransition.DISAPPEARING); + transition.enableTransitionType(LayoutTransition.CHANGE_APPEARING); + transition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); + } + + private void disableLayoutTransitions() { + LayoutTransition transition = getLayoutTransition(); + transition.disableTransitionType(LayoutTransition.APPEARING); + transition.disableTransitionType(LayoutTransition.DISAPPEARING); + transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); + transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); + } + + public void offsetWindowCenterTo(int activeIndex, boolean allowAnimations) { + if (activeIndex < 0) { + new Throwable().printStackTrace(); + } + int windowSize = Math.min(mMarkers.size(), mMaxWindowSize); + int hWindowSize = (int) windowSize / 2; + float hfWindowSize = windowSize / 2f; + int windowStart = Math.max(0, activeIndex - hWindowSize); + int windowEnd = Math.min(mMarkers.size(), windowStart + mMaxWindowSize); + windowStart = windowEnd - Math.min(mMarkers.size(), windowSize); + int windowMid = windowStart + (windowEnd - windowStart) / 2; + boolean windowAtStart = (windowStart == 0); + boolean windowAtEnd = (windowEnd == mMarkers.size()); + boolean windowMoved = (mWindowRange[0] != windowStart) || + (mWindowRange[1] != windowEnd); + + if (!allowAnimations) { + disableLayoutTransitions(); + } + + // Remove all the previous children that are no longer in the window + for (int i = getChildCount() - 1; i >= 0; --i) { + PageIndicatorDot marker = (PageIndicatorDot) getChildAt(i); + int markerIndex = mMarkers.indexOf(marker); + if (markerIndex < windowStart || markerIndex >= windowEnd) { + removeView(marker); + } + } + + // Add all the new children that belong in the window + for (int i = 0; i < mMarkers.size(); ++i) { + PageIndicatorDot marker = (PageIndicatorDot) mMarkers.get(i); + if (windowStart <= i && i < windowEnd) { + if (indexOfChild(marker) < 0) { + addView(marker, i - windowStart); + } + if (i == activeIndex) { + marker.activate(windowMoved); + } else { + marker.inactivate(windowMoved); + } + } else { + marker.inactivate(true); + } + + if (MODULATE_ALPHA_ENABLED) { + // Update the marker's alpha + float alpha = 1f; + if (mMarkers.size() > windowSize) { + if ((windowAtStart && i > hWindowSize) || + (windowAtEnd && i < (mMarkers.size() - hWindowSize)) || + (!windowAtStart && !windowAtEnd)) { + alpha = 1f - Math.abs((i - windowMid) / hfWindowSize); + } + } + marker.animate().alpha(alpha).setDuration(500).start(); + } + } + + if (!allowAnimations) { + enableLayoutTransitions(); + } + + mWindowRange[0] = windowStart; + mWindowRange[1] = windowEnd; + } + + @Override + public void addMarker(int index, PageMarkerResources marker, boolean allowAnimations) { + index = Math.max(0, Math.min(index, mMarkers.size())); + + PageIndicatorDot m = + (PageIndicatorDot) mLayoutInflater.inflate(R.layout.page_indicator_marker, + this, false); + m.setMarkerDrawables(marker.activeId, marker.inactiveId); + + mMarkers.add(index, m); + offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); + } + + @Override + public void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations) { + for (int i = 0; i < markers.size(); ++i) { + addMarker(Integer.MAX_VALUE, markers.get(i), allowAnimations); + } + } + + @Override + public void updateMarker(int index, PageMarkerResources marker) { + PageIndicatorDot m = mMarkers.get(index); + m.setMarkerDrawables(marker.activeId, marker.inactiveId); + } + + @Override + public void removeMarker(int index, boolean allowAnimations) { + if (mMarkers.size() > 0) { + index = Math.max(0, Math.min(mMarkers.size() - 1, index)); + mMarkers.remove(index); + offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); + } + } + + @Override + public View getView() { + return this; + } + + @Override + public void setProgress(float progress) { + } + + @Override + public void removeAllMarkers(boolean allowAnimations) { + while (mMarkers.size() > 0) { + removeMarker(Integer.MAX_VALUE, allowAnimations); + } + } + + @Override + public void setActiveMarker(int index) { + // Center the active marker + mActiveMarkerIndex = index; + offsetWindowCenterTo(index, false); + } + + private void dumpState(String txt) { + System.out.println(txt); + System.out.println("\tmMarkers: " + mMarkers.size()); + for (int i = 0; i < mMarkers.size(); ++i) { + PageIndicatorDot m = mMarkers.get(i); + System.out.println("\t\t(" + i + ") " + m); + } + System.out.println("\twindow: [" + mWindowRange[0] + ", " + mWindowRange[1] + "]"); + System.out.println("\tchildren: " + getChildCount()); + for (int i = 0; i < getChildCount(); ++i) { + PageIndicatorDot m = (PageIndicatorDot) getChildAt(i); + System.out.println("\t\t(" + i + ") " + m); + } + System.out.println("\tactive: " + mActiveMarkerIndex); + } +} |