mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-18 10:18:20 +00:00
219 lines
8.2 KiB
Java
219 lines
8.2 KiB
Java
/*
|
|
* 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;
|
|
|
|
import android.animation.LayoutTransition;
|
|
import android.content.Context;
|
|
import android.content.res.TypedArray;
|
|
import android.util.AttributeSet;
|
|
import android.view.LayoutInflater;
|
|
import android.widget.LinearLayout;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
public class PageIndicator extends LinearLayout {
|
|
@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<PageIndicatorMarker> mMarkers =
|
|
new ArrayList<PageIndicatorMarker>();
|
|
private int mActiveMarkerIndex;
|
|
|
|
public static class PageMarkerResources {
|
|
int activeId;
|
|
int inactiveId;
|
|
|
|
public PageMarkerResources() {
|
|
activeId = R.drawable.ic_pageindicator_current;
|
|
inactiveId = R.drawable.ic_pageindicator_default;
|
|
}
|
|
public PageMarkerResources(int aId, int iaId) {
|
|
activeId = aId;
|
|
inactiveId = iaId;
|
|
}
|
|
}
|
|
|
|
public PageIndicator(Context context) {
|
|
this(context, null);
|
|
}
|
|
|
|
public PageIndicator(Context context, AttributeSet attrs) {
|
|
this(context, attrs, 0);
|
|
}
|
|
|
|
public PageIndicator(Context context, AttributeSet attrs, int defStyle) {
|
|
super(context, attrs, defStyle);
|
|
TypedArray a = context.obtainStyledAttributes(attrs,
|
|
R.styleable.PageIndicator, defStyle, 0);
|
|
mMaxWindowSize = a.getInteger(R.styleable.PageIndicator_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);
|
|
}
|
|
|
|
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) {
|
|
PageIndicatorMarker marker = (PageIndicatorMarker) 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) {
|
|
PageIndicatorMarker marker = (PageIndicatorMarker) 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;
|
|
}
|
|
|
|
void addMarker(int index, PageMarkerResources marker, boolean allowAnimations) {
|
|
index = Math.max(0, Math.min(index, mMarkers.size()));
|
|
|
|
PageIndicatorMarker m =
|
|
(PageIndicatorMarker) mLayoutInflater.inflate(R.layout.page_indicator_marker,
|
|
this, false);
|
|
m.setMarkerDrawables(marker.activeId, marker.inactiveId);
|
|
|
|
mMarkers.add(index, m);
|
|
offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations);
|
|
}
|
|
void addMarkers(ArrayList<PageMarkerResources> markers, boolean allowAnimations) {
|
|
for (int i = 0; i < markers.size(); ++i) {
|
|
addMarker(Integer.MAX_VALUE, markers.get(i), allowAnimations);
|
|
}
|
|
}
|
|
|
|
void updateMarker(int index, PageMarkerResources marker) {
|
|
PageIndicatorMarker m = mMarkers.get(index);
|
|
m.setMarkerDrawables(marker.activeId, marker.inactiveId);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
void removeAllMarkers(boolean allowAnimations) {
|
|
while (mMarkers.size() > 0) {
|
|
removeMarker(Integer.MAX_VALUE, allowAnimations);
|
|
}
|
|
}
|
|
|
|
void setActiveMarker(int index) {
|
|
// Center the active marker
|
|
mActiveMarkerIndex = index;
|
|
offsetWindowCenterTo(index, false);
|
|
}
|
|
|
|
void dumpState(String txt) {
|
|
System.out.println(txt);
|
|
System.out.println("\tmMarkers: " + mMarkers.size());
|
|
for (int i = 0; i < mMarkers.size(); ++i) {
|
|
PageIndicatorMarker 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) {
|
|
PageIndicatorMarker m = (PageIndicatorMarker) getChildAt(i);
|
|
System.out.println("\t\t(" + i + ") " + m);
|
|
}
|
|
System.out.println("\tactive: " + mActiveMarkerIndex);
|
|
}
|
|
}
|