124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller/* 224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Copyright (C) 2009 The Android Open Source Project 324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * you may not use this file except in compliance with the License. 624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * You may obtain a copy of the License at 724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * http://www.apache.org/licenses/LICENSE-2.0 924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 1024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Unless required by applicable law or agreed to in writing, software 1124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * distributed under the License is distributed on an "AS IS" BASIS, 1224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * See the License for the specific language governing permissions and 1424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * limitations under the License. 1524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 1624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 1724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerpackage com.android.internal.widget; 1824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 1924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.content.Context; 201d0a152fa8905b9dfb87dc87da8e5432e48eae96Jim Millerimport android.content.res.Configuration; 2124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.content.res.Resources; 2224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.content.res.TypedArray; 23521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.graphics.Canvas; 2424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.graphics.Rect; 25753401aa471d2fb87ab937c2b02b182ebc215c3aJim Millerimport android.graphics.drawable.Drawable; 2624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.os.Vibrator; 2724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.util.AttributeSet; 2824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.util.Log; 2924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.view.Gravity; 3024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.view.MotionEvent; 3124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.view.View; 3224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.view.ViewGroup; 33521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.view.animation.AlphaAnimation; 34521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.view.animation.Animation; 35521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.view.animation.LinearInterpolator; 36521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.view.animation.TranslateAnimation; 37521d400b230bee5e7b9748f26832c0d0275b8253Jim Millerimport android.view.animation.Animation.AnimationListener; 3824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.widget.ImageView; 3924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.widget.TextView; 4024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport android.widget.ImageView.ScaleType; 4124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerimport com.android.internal.R; 4224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 4324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller/** 4424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * A special widget containing two Sliders and a threshold for each. Moving either slider beyond 45425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * the threshold will cause the registered OnTriggerListener.onTrigger() to be called with 464df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * whichHandle being {@link OnTriggerListener#LEFT_HANDLE} or {@link OnTriggerListener#RIGHT_HANDLE} 47425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * Equivalently, selecting a tab will result in a call to 484df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * {@link OnTriggerListener#onGrabbedStateChange(View, int)} with one of these two states. Releasing 494df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * the tab will result in whichHandle being {@link OnTriggerListener#NO_HANDLE}. 5024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 5124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 5224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Millerpublic class SlidingTab extends ViewGroup { 5324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final String LOG_TAG = "SlidingTab"; 5424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final boolean DBG = false; 5524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final int HORIZONTAL = 0; // as defined in attrs.xml 5624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final int VERTICAL = 1; 5724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 5824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // TODO: Make these configurable 594df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller private static final float THRESHOLD = 2.0f / 3.0f; 6024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final long VIBRATE_SHORT = 30; 6124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final long VIBRATE_LONG = 40; 62521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private static final int TRACKING_MARGIN = 50; 63521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private static final int ANIM_DURATION = 250; // Time for most animations (in ms) 64521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private static final int ANIM_TARGET_TIME = 500; // Time to show targets (in ms) 654f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller private boolean mHoldLeftOnTransition = true; 664f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller private boolean mHoldRightOnTransition = true; 6724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 6824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private OnTriggerListener mOnTriggerListener; 6924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private int mGrabbedState = OnTriggerListener.NO_HANDLE; 7024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private boolean mTriggered = false; 7124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private Vibrator mVibrator; 7224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private float mDensity; // used to scale dimensions for bitmaps. 7324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 7424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 7524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Either {@link #HORIZONTAL} or {@link #VERTICAL}. 7624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 7724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private int mOrientation; 7824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 7924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private Slider mLeftSlider; 8024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private Slider mRightSlider; 8124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private Slider mCurrentSlider; 8224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private boolean mTracking; 834df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller private float mThreshold; 8424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private Slider mOtherSlider; 8524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private boolean mAnimating; 86521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private Rect mTmpRect; 8724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 8824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 894f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller * Listener used to reset the view when the current animation completes. 904f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller */ 914f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller private final AnimationListener mAnimationDoneListener = new AnimationListener() { 924f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void onAnimationStart(Animation animation) { 934f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 944f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 954f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 964f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void onAnimationRepeat(Animation animation) { 974f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 984f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 994f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 1004f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void onAnimationEnd(Animation animation) { 1014f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller onAnimationDone(); 1024f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 1034f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller }; 1044f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 1054f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller /** 10624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Interface definition for a callback to be invoked when a tab is triggered 1074df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * by moving it beyond a threshold. 10824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 10924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public interface OnTriggerListener { 11024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 11124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * The interface was triggered because the user let go of the handle without reaching the 1124df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * threshold. 11324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 11424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int NO_HANDLE = 0; 11524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 11624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 11724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * The interface was triggered because the user grabbed the left handle and moved it past 1184df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * the threshold. 11924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 12024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int LEFT_HANDLE = 1; 12124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 12224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 12324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * The interface was triggered because the user grabbed the right handle and moved it past 1244df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * the threshold. 12524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 12624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int RIGHT_HANDLE = 2; 12724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 12824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 1294df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller * Called when the user moves a handle beyond the threshold. 13024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 13124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param v The view that was triggered. 13224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param whichHandle Which "dial handle" the user grabbed, 13324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * either {@link #LEFT_HANDLE}, {@link #RIGHT_HANDLE}. 13424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 13524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void onTrigger(View v, int whichHandle); 13624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 13724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 13824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Called when the "grabbed state" changes (i.e. when the user either grabs or releases 13924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * one of the handles.) 14024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 14124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param v the view that was triggered 14224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param grabbedState the new state: {@link #NO_HANDLE}, {@link #LEFT_HANDLE}, 14324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * or {@link #RIGHT_HANDLE}. 14424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 14524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void onGrabbedStateChange(View v, int grabbedState); 14624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 14724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 14824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 149425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * Simple container class for all things pertinent to a slider. 15024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * A slider consists of 3 Views: 151425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * 15224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * {@link #tab} is the tab shown on the screen in the default state. 15324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * {@link #text} is the view revealed as the user slides the tab out. 15424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * {@link #target} is the target the user must drag the slider past to trigger the slider. 15524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 15624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 15724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static class Slider { 15824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 15924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Tab alignment - determines which side the tab should be drawn on 16024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 16124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int ALIGN_LEFT = 0; 16224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int ALIGN_RIGHT = 1; 16324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int ALIGN_TOP = 2; 16424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public static final int ALIGN_BOTTOM = 3; 165521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller public static final int ALIGN_UNKNOWN = 4; 16624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 16724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 16824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * States for the view. 16924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 17024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final int STATE_NORMAL = 0; 17124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final int STATE_PRESSED = 1; 17224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private static final int STATE_ACTIVE = 2; 17324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 17424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private final ImageView tab; 17524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private final TextView text; 17624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private final ImageView target; 1774df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller private int currentState = STATE_NORMAL; 178521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private int alignment = ALIGN_UNKNOWN; 179521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private int alignment_value; 18024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 18124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 18224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Constructor 183425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * 18424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param parent the container view of this one 18524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param tabId drawable for the tab 18624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param barId drawable for the bar 18724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param targetId drawable for the target 18824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 18924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller Slider(ViewGroup parent, int tabId, int barId, int targetId) { 19024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // Create tab 19124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab = new ImageView(parent.getContext()); 19224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setBackgroundResource(tabId); 19324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setScaleType(ScaleType.CENTER); 19424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 19524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller LayoutParams.WRAP_CONTENT)); 19624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 19724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // Create hint TextView 19824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text = new TextView(parent.getContext()); 19924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, 200980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy LayoutParams.MATCH_PARENT)); 20124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setBackgroundResource(barId); 20224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setTextAppearance(parent.getContext(), R.style.TextAppearance_SlidingTabNormal); 20324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // hint.setSingleLine(); // Hmm.. this causes the text to disappear off-screen 20424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 20524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // Create target 20624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target = new ImageView(parent.getContext()); 20724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setImageResource(targetId); 20824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setScaleType(ScaleType.CENTER); 20924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setLayoutParams( 21024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 21124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setVisibility(View.INVISIBLE); 21224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 21324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller parent.addView(target); // this needs to be first - relies on painter's algorithm 21424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller parent.addView(tab); 21524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller parent.addView(text); 21624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 21724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 21824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setIcon(int iconId) { 21924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setImageResource(iconId); 22024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 221425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller 22224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setTabBackgroundResource(int tabId) { 22324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setBackgroundResource(tabId); 22424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 225425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller 22624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setBarBackgroundResource(int barId) { 22724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setBackgroundResource(barId); 22824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 229425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller 23024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setHintText(int resId) { 231425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller text.setText(resId); 23224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 23324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 23424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void hide() { 235521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller boolean horiz = alignment == ALIGN_LEFT || alignment == ALIGN_RIGHT; 236521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dx = horiz ? (alignment == ALIGN_LEFT ? alignment_value - tab.getRight() 237521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller : alignment_value - tab.getLeft()) : 0; 238521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dy = horiz ? 0 : (alignment == ALIGN_TOP ? alignment_value - tab.getBottom() 239521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller : alignment_value - tab.getTop()); 240521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 241521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller Animation trans = new TranslateAnimation(0, dx, 0, dy); 242521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller trans.setDuration(ANIM_DURATION); 243521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller trans.setFillAfter(true); 244521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.startAnimation(trans); 245521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.startAnimation(trans); 24624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setVisibility(View.INVISIBLE); 24724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 24824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 249521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller void show(boolean animate) { 250521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.setVisibility(View.VISIBLE); 251521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.setVisibility(View.VISIBLE); 252521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller //target.setVisibility(View.INVISIBLE); 253521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (animate) { 254521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller boolean horiz = alignment == ALIGN_LEFT || alignment == ALIGN_RIGHT; 255521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dx = horiz ? (alignment == ALIGN_LEFT ? tab.getWidth() : -tab.getWidth()) : 0; 256521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dy = horiz ? 0: (alignment == ALIGN_TOP ? tab.getHeight() : -tab.getHeight()); 257521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 258521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller Animation trans = new TranslateAnimation(-dx, 0, -dy, 0); 259521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller trans.setDuration(ANIM_DURATION); 260521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.startAnimation(trans); 261521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.startAnimation(trans); 262521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 263521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 264521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 26524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setState(int state) { 26624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setPressed(state == STATE_PRESSED); 26724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setPressed(state == STATE_PRESSED); 26824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (state == STATE_ACTIVE) { 26924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int[] activeState = new int[] {com.android.internal.R.attr.state_active}; 27024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (text.getBackground().isStateful()) { 27124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.getBackground().setState(activeState); 27224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 27324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (tab.getBackground().isStateful()) { 27424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.getBackground().setState(activeState); 27524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 27624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabActive); 27724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 27824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabNormal); 27924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 2804df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller currentState = state; 28124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 28224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 28324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void showTarget() { 284521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller AlphaAnimation alphaAnim = new AlphaAnimation(0.0f, 1.0f); 285521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller alphaAnim.setDuration(ANIM_TARGET_TIME); 286521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller target.startAnimation(alphaAnim); 28724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setVisibility(View.VISIBLE); 28824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 28924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 290521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller void reset(boolean animate) { 29124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller setState(STATE_NORMAL); 29224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setVisibility(View.VISIBLE); 29324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setTextAppearance(text.getContext(), R.style.TextAppearance_SlidingTabNormal); 29424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.setVisibility(View.VISIBLE); 29524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setVisibility(View.INVISIBLE); 296521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller final boolean horiz = alignment == ALIGN_LEFT || alignment == ALIGN_RIGHT; 297521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dx = horiz ? (alignment == ALIGN_LEFT ? alignment_value - tab.getLeft() 298521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller : alignment_value - tab.getRight()) : 0; 299521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int dy = horiz ? 0 : (alignment == ALIGN_TOP ? alignment_value - tab.getTop() 300521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller : alignment_value - tab.getBottom()); 301521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (animate) { 302521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller TranslateAnimation trans = new TranslateAnimation(0, dx, 0, dy); 303521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller trans.setDuration(ANIM_DURATION); 304521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller trans.setFillAfter(false); 305521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.startAnimation(trans); 306521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.startAnimation(trans); 307521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } else { 308521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (horiz) { 309521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.offsetLeftAndRight(dx); 310521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.offsetLeftAndRight(dx); 311521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } else { 312521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller text.offsetTopAndBottom(dy); 313521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller tab.offsetTopAndBottom(dy); 314521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 3154f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller text.clearAnimation(); 3164f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller tab.clearAnimation(); 3174f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller target.clearAnimation(); 318521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 31924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 32024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 32124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void setTarget(int targetId) { 32224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.setImageResource(targetId); 32324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 32424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 32524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 32624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Layout the given widgets within the parent. 32724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 32824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param l the parent's left border 32924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param t the parent's top border 33024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param r the parent's right border 33124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param b the parent's bottom border 33224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param alignment which side to align the widget to 33324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 33424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller void layout(int l, int t, int r, int b, int alignment) { 335521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller this.alignment = alignment; 336753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final Drawable tabBackground = tab.getBackground(); 337753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final int handleWidth = tabBackground.getIntrinsicWidth(); 338753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final int handleHeight = tabBackground.getIntrinsicHeight(); 339753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final Drawable targetDrawable = target.getDrawable(); 340753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final int targetWidth = targetDrawable.getIntrinsicWidth(); 341753401aa471d2fb87ab937c2b02b182ebc215c3aJim Miller final int targetHeight = targetDrawable.getIntrinsicHeight(); 34224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int parentWidth = r - l; 34324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int parentHeight = b - t; 34424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 3454df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller final int leftTarget = (int) (THRESHOLD * parentWidth) - targetWidth + handleWidth / 2; 3464df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller final int rightTarget = (int) ((1.0f - THRESHOLD) * parentWidth) - handleWidth / 2; 34724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int left = (parentWidth - handleWidth) / 2; 34824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int right = left + handleWidth; 34924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 35024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (alignment == ALIGN_LEFT || alignment == ALIGN_RIGHT) { 35124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // horizontal 35224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int targetTop = (parentHeight - targetHeight) / 2; 35324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int targetBottom = targetTop + targetHeight; 35424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int top = (parentHeight - handleHeight) / 2; 35524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int bottom = (parentHeight + handleHeight) / 2; 35624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (alignment == ALIGN_LEFT) { 35724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.layout(0, top, handleWidth, bottom); 35824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.layout(0 - parentWidth, top, 0, bottom); 35924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setGravity(Gravity.RIGHT); 36024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.layout(leftTarget, targetTop, leftTarget + targetWidth, targetBottom); 361521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller alignment_value = l; 36224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 36324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.layout(parentWidth - handleWidth, top, parentWidth, bottom); 36424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.layout(parentWidth, top, parentWidth + parentWidth, bottom); 36524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.layout(rightTarget, targetTop, rightTarget + targetWidth, targetBottom); 36624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.setGravity(Gravity.TOP); 367521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller alignment_value = r; 36824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 36924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 37024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // vertical 37124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int targetLeft = (parentWidth - targetWidth) / 2; 37224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int targetRight = (parentWidth + targetWidth) / 2; 3734df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller final int top = (int) (THRESHOLD * parentHeight) + handleHeight / 2 - targetHeight; 3744df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller final int bottom = (int) ((1.0f - THRESHOLD) * parentHeight) - handleHeight / 2; 37524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (alignment == ALIGN_TOP) { 37624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.layout(left, 0, right, handleHeight); 37724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.layout(left, 0 - parentHeight, right, 0); 37824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.layout(targetLeft, top, targetRight, top + targetHeight); 379521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller alignment_value = t; 38024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 38124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller tab.layout(left, parentHeight - handleHeight, right, parentHeight); 38224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller text.layout(left, parentHeight, right, parentHeight + parentHeight); 38324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller target.layout(targetLeft, bottom, targetRight, bottom + targetHeight); 384521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller alignment_value = b; 38524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 38624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 38724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 38824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 3894df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller public void updateDrawableStates() { 3904df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller setState(currentState); 3914df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller } 3924df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller 3934811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller /** 3944811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller * Ensure all the dependent widgets are measured. 3954811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller */ 3964811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller public void measure() { 3974811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller tab.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 3984811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 3994811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller text.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), 4004811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); 4014811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller } 4024811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller 4034811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller /** 4044811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller * Get the measured tab width. Must be called after {@link Slider#measure()}. 4054811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller * @return 4064811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller */ 40724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public int getTabWidth() { 4084811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller return tab.getMeasuredWidth(); 40924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 41024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 4114811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller /** 4124811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller * Get the measured tab width. Must be called after {@link Slider#measure()}. 4134811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller * @return 4144811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller */ 41524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public int getTabHeight() { 4164811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller return tab.getMeasuredHeight(); 41724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 418521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 4198b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller /** 4208b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller * Start animating the slider. Note we need two animations since an Animator 4218b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller * keeps internal state of the invalidation region which is just the view being animated. 4222cd1e6eda90170114e0795b13f65f964296cf2f2Jim Miller * 4238b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller * @param anim1 4248b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller * @param anim2 4258b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller */ 4268b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller public void startAnimation(Animation anim1, Animation anim2) { 4278b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller tab.startAnimation(anim1); 4288b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller text.startAnimation(anim2); 4294f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 4304f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 4314f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void hideTarget() { 4324f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller target.clearAnimation(); 4334f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller target.setVisibility(View.INVISIBLE); 434521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 43524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 43624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 43724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public SlidingTab(Context context) { 43824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller this(context, null); 43924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 44024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 44124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 44224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Constructor used when this widget is created from a layout file. 44324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 44424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public SlidingTab(Context context, AttributeSet attrs) { 44524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller super(context, attrs); 44624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 447521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller // Allocate a temporary once that can be used everywhere. 448521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mTmpRect = new Rect(); 449521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 45024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingTab); 45124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOrientation = a.getInt(R.styleable.SlidingTab_orientation, HORIZONTAL); 45224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller a.recycle(); 45324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 45424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller Resources r = getResources(); 45524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mDensity = r.getDisplayMetrics().density; 45624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (DBG) log("- Density: " + mDensity); 45724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 458425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mLeftSlider = new Slider(this, 459425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller R.drawable.jog_tab_left_generic, 46024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller R.drawable.jog_tab_bar_left_generic, 46124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller R.drawable.jog_tab_target_gray); 462425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mRightSlider = new Slider(this, 463425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller R.drawable.jog_tab_right_generic, 46424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller R.drawable.jog_tab_bar_right_generic, 46524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller R.drawable.jog_tab_target_gray); 46624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 46724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // setBackgroundColor(0x80808080); 46824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 46924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 47024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller @Override 47124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 47224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); 47324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 47424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 47524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); 47624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 47724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 47824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) { 479966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller Log.e("SlidingTab", "SlidingTab cannot have UNSPECIFIED MeasureSpec" 480966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller +"(wspec=" + widthSpecMode + ", hspec=" + heightSpecMode + ")", 481966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller new RuntimeException(LOG_TAG + "stack:")); 48224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 48324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 4844811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller mLeftSlider.measure(); 4854811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller mRightSlider.measure(); 4864811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller final int leftTabWidth = mLeftSlider.getTabWidth(); 4874811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller final int rightTabWidth = mRightSlider.getTabWidth(); 4884811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller final int leftTabHeight = mLeftSlider.getTabHeight(); 4894811d62d5f07a1ffbf085d5e424e2b54d0e7ebfdJim Miller final int rightTabHeight = mRightSlider.getTabHeight(); 49024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int width; 49124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int height; 49224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (isHorizontal()) { 49324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller width = Math.max(widthSpecSize, leftTabWidth + rightTabWidth); 49424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller height = Math.max(leftTabHeight, rightTabHeight); 49524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 49624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller width = Math.max(leftTabWidth, rightTabHeight); 49724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller height = Math.max(heightSpecSize, leftTabHeight + rightTabHeight); 49824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 49924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller setMeasuredDimension(width, height); 50024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 50124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 50224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller @Override 50324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public boolean onInterceptTouchEvent(MotionEvent event) { 50424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int action = event.getAction(); 50524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final float x = event.getX(); 50624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final float y = event.getY(); 50724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 50824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (mAnimating) { 50924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller return false; 51024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 51124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 51224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller View leftHandle = mLeftSlider.tab; 513521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller leftHandle.getHitRect(mTmpRect); 514521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller boolean leftHit = mTmpRect.contains((int) x, (int) y); 51524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 51624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller View rightHandle = mRightSlider.tab; 517521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller rightHandle.getHitRect(mTmpRect); 518521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller boolean rightHit = mTmpRect.contains((int)x, (int) y); 51924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 52024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (!mTracking && !(leftHit || rightHit)) { 52124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller return false; 52224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 52324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 52424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller switch (action) { 52524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller case MotionEvent.ACTION_DOWN: { 52624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mTracking = true; 52724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mTriggered = false; 52824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller vibrate(VIBRATE_SHORT); 52924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (leftHit) { 53024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mCurrentSlider = mLeftSlider; 53124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOtherSlider = mRightSlider; 5324df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller mThreshold = isHorizontal() ? THRESHOLD : 1.0f - THRESHOLD; 53324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller setGrabbedState(OnTriggerListener.LEFT_HANDLE); 53424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 53524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mCurrentSlider = mRightSlider; 53624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOtherSlider = mLeftSlider; 5374df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller mThreshold = isHorizontal() ? 1.0f - THRESHOLD : THRESHOLD; 53824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller setGrabbedState(OnTriggerListener.RIGHT_HANDLE); 53924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 54024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mCurrentSlider.setState(Slider.STATE_PRESSED); 54124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mCurrentSlider.showTarget(); 54224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOtherSlider.hide(); 54324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller break; 54424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 54524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 54624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 54724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller return true; 54824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 54924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 550d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller /** 551d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller * Reset the tabs to their original state and stop any existing animation. 552d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller * Animate them back into place if animate is true. 553d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller * 554d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller * @param animate 555d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller */ 556d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller public void reset(boolean animate) { 557d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller mLeftSlider.reset(animate); 558d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller mRightSlider.reset(animate); 559966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller if (!animate) { 560966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller mAnimating = false; 561966a8c78598bdba1e8993428b5b1eef4d97ae501Jim Miller } 562d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller } 563d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller 56424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller @Override 5654f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void setVisibility(int visibility) { 5664f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller // Clear animations so sliders don't continue to animate when we show the widget again. 5674f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller if (visibility != getVisibility() && visibility == View.INVISIBLE) { 568d8a3a8957b9d71ab75584b0cc98324fd70cc527cJim Miller reset(false); 5694f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 5704f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller super.setVisibility(visibility); 5714f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 5724f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 5734f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller @Override 57424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public boolean onTouchEvent(MotionEvent event) { 57524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (mTracking) { 57624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final int action = event.getAction(); 57724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final float x = event.getX(); 57824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final float y = event.getY(); 579521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 58024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller switch (action) { 58124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller case MotionEvent.ACTION_MOVE: 582521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (withinView(x, y, this) ) { 583521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller moveHandle(x, y); 584521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller float position = isHorizontal() ? x : y; 585521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller float target = mThreshold * (isHorizontal() ? getWidth() : getHeight()); 586521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller boolean thresholdReached; 587521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (isHorizontal()) { 588521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller thresholdReached = mCurrentSlider == mLeftSlider ? 589521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller position > target : position < target; 590521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } else { 591521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller thresholdReached = mCurrentSlider == mLeftSlider ? 592521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller position < target : position > target; 593521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 594521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (!mTriggered && thresholdReached) { 595521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mTriggered = true; 596521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mTracking = false; 597521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mCurrentSlider.setState(Slider.STATE_ACTIVE); 5984f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller boolean isLeft = mCurrentSlider == mLeftSlider; 5994f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller dispatchTriggerEvent(isLeft ? 600521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller OnTriggerListener.LEFT_HANDLE : OnTriggerListener.RIGHT_HANDLE); 601521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 6024f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller startAnimating(isLeft ? mHoldLeftOnTransition : mHoldRightOnTransition); 603521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller setGrabbedState(OnTriggerListener.NO_HANDLE); 604521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 60524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller break; 60624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 60724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // Intentionally fall through - we're outside tracking rectangle 60824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 60924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller case MotionEvent.ACTION_UP: 61024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller case MotionEvent.ACTION_CANCEL: 61124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mTracking = false; 61224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mTriggered = false; 613521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mOtherSlider.show(true); 614521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mCurrentSlider.reset(false); 6154f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller mCurrentSlider.hideTarget(); 616521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mCurrentSlider = null; 617521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mOtherSlider = null; 61824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller setGrabbedState(OnTriggerListener.NO_HANDLE); 61924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller break; 62024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 62124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 62224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 62324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller return mTracking || super.onTouchEvent(event); 62424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 62524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 6264f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller void startAnimating(final boolean holdAfter) { 627521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mAnimating = true; 6288b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller final Animation trans1; 6298b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller final Animation trans2; 6304f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller final Slider slider = mCurrentSlider; 6314f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller final Slider other = mOtherSlider; 6324f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller final int dx; 6334f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller final int dy; 634521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller if (isHorizontal()) { 635521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int right = slider.tab.getRight(); 636521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int width = slider.tab.getWidth(); 637521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int left = slider.tab.getLeft(); 638521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int viewWidth = getWidth(); 6394f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller int holdOffset = holdAfter ? 0 : width; // how much of tab to show at the end of anim 6404f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller dx = slider == mRightSlider ? - (right + viewWidth - holdOffset) 6414f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller : (viewWidth - left) + viewWidth - holdOffset; 642521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller dy = 0; 643521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } else { 644521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int top = slider.tab.getTop(); 645521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int bottom = slider.tab.getBottom(); 646521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int height = slider.tab.getHeight(); 647521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller int viewHeight = getHeight(); 6484f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller int holdOffset = holdAfter ? 0 : height; // how much of tab to show at end of anim 649521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller dx = 0; 6504f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller dy = slider == mRightSlider ? (top + viewHeight - holdOffset) 6514f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller : - ((viewHeight - bottom) + viewHeight - holdOffset); 652521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 6538b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans1 = new TranslateAnimation(0, dx, 0, dy); 6548b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans1.setDuration(ANIM_DURATION); 6558b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans1.setInterpolator(new LinearInterpolator()); 6568b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans1.setFillAfter(true); 6578b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans2 = new TranslateAnimation(0, dx, 0, dy); 6588b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans2.setDuration(ANIM_DURATION); 6598b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans2.setInterpolator(new LinearInterpolator()); 6608b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans2.setFillAfter(true); 6618b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller 6628b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller trans1.setAnimationListener(new AnimationListener() { 663521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller public void onAnimationEnd(Animation animation) { 6644f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller Animation anim; 6654f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller if (holdAfter) { 6664f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller anim = new TranslateAnimation(dx, dx, dy, dy); 6674f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller anim.setDuration(1000); // plenty of time for transitions 6684f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller mAnimating = false; 6694f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } else { 6704f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller anim = new AlphaAnimation(0.5f, 1.0f); 6714f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller anim.setDuration(ANIM_DURATION); 6724f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller resetView(); 6734f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 6744f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller anim.setAnimationListener(mAnimationDoneListener); 6752cd1e6eda90170114e0795b13f65f964296cf2f2Jim Miller 6768b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller /* Animation can be the same for these since the animation just holds */ 6778b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller mLeftSlider.startAnimation(anim, anim); 6788b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller mRightSlider.startAnimation(anim, anim); 679521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 680521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 681521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller public void onAnimationRepeat(Animation animation) { 682521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 683521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 684521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 685521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller public void onAnimationStart(Animation animation) { 686521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 687521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 688521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 689521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller }); 690521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 6914f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller slider.hideTarget(); 6928b63ab664ff5068d022c080ce04995a0bfdd7030Jim Miller slider.startAnimation(trans1, trans2); 693521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 694521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 6954f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller private void onAnimationDone() { 6964f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller resetView(); 6974f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller mAnimating = false; 6984f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 6994f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 700521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller private boolean withinView(final float x, final float y, final View view) { 701521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller return isHorizontal() && y > - TRACKING_MARGIN && y < TRACKING_MARGIN + view.getHeight() 702521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller || !isHorizontal() && x > -TRACKING_MARGIN && x < TRACKING_MARGIN + view.getWidth(); 703521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller } 704521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller 70524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private boolean isHorizontal() { 70624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller return mOrientation == HORIZONTAL; 70724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 70824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 70924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private void resetView() { 710521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mLeftSlider.reset(false); 711521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller mRightSlider.reset(false); 712521d400b230bee5e7b9748f26832c0d0275b8253Jim Miller // onLayout(true, getLeft(), getTop(), getLeft() + getWidth(), getTop() + getHeight()); 71324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 71424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 71524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller @Override 71624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller protected void onLayout(boolean changed, int l, int t, int r, int b) { 71724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (!changed) return; 71824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 71924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller // Center the widgets in the view 72024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mLeftSlider.layout(l, t, r, b, isHorizontal() ? Slider.ALIGN_LEFT : Slider.ALIGN_BOTTOM); 72124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mRightSlider.layout(l, t, r, b, isHorizontal() ? Slider.ALIGN_RIGHT : Slider.ALIGN_TOP); 72224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 72324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 72424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private void moveHandle(float x, float y) { 72524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final View handle = mCurrentSlider.tab; 72624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller final View content = mCurrentSlider.text; 72724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (isHorizontal()) { 72824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int deltaX = (int) x - handle.getLeft() - (handle.getWidth() / 2); 72924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller handle.offsetLeftAndRight(deltaX); 73024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller content.offsetLeftAndRight(deltaX); 73124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } else { 73224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller int deltaY = (int) y - handle.getTop() - (handle.getHeight() / 2); 73324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller handle.offsetTopAndBottom(deltaY); 73424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller content.offsetTopAndBottom(deltaY); 73524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 73624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller invalidate(); // TODO: be more conservative about what we're invalidating 73724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 73824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 73924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 74024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Sets the left handle icon to a given resource. 74124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 74224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * The resource should refer to a Drawable object, or use 0 to remove 74324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * the icon. 74424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 74524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param iconId the resource ID of the icon drawable 74624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param targetId the resource of the target drawable 74724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param barId the resource of the bar drawable (stateful) 748425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * @param tabId the resource of the 74924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 75024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public void setLeftTabResources(int iconId, int targetId, int barId, int tabId) { 75124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mLeftSlider.setIcon(iconId); 752425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mLeftSlider.setTarget(targetId); 75324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mLeftSlider.setBarBackgroundResource(barId); 75424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mLeftSlider.setTabBackgroundResource(tabId); 7554df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller mLeftSlider.updateDrawableStates(); 75624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 75724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 75824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 75924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Sets the left handle hint text to a given resource string. 76024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 76124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param resId 76224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 76324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public void setLeftHintText(int resId) { 764425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller if (isHorizontal()) { 765425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mLeftSlider.setHintText(resId); 766425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller } 76724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 76824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 76924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 77024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Sets the right handle icon to a given resource. 77124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 77224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * The resource should refer to a Drawable object, or use 0 to remove 77324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * the icon. 77424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 77524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param iconId the resource ID of the icon drawable 77624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param targetId the resource of the target drawable 77724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param barId the resource of the bar drawable (stateful) 778425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller * @param tabId the resource of the 77924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 78024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public void setRightTabResources(int iconId, int targetId, int barId, int tabId) { 78124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mRightSlider.setIcon(iconId); 782425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mRightSlider.setTarget(targetId); 78324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mRightSlider.setBarBackgroundResource(barId); 78424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mRightSlider.setTabBackgroundResource(tabId); 7854df2c5433bb530fae6191a0298a6d494ca03eaa7Jim Miller mRightSlider.updateDrawableStates(); 78624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 78724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 78824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 78924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Sets the left handle hint text to a given resource string. 79024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 79124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param resId 79224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 79324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public void setRightHintText(int resId) { 794425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller if (isHorizontal()) { 795425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller mRightSlider.setHintText(resId); 796425ca595dcc37ddb7a9f96310e5b800f424811a6Jim Miller } 79724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 79824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 7994f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller public void setHoldAfterTrigger(boolean holdLeft, boolean holdRight) { 8004f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller mHoldLeftOnTransition = holdLeft; 8014f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller mHoldRightOnTransition = holdRight; 8024f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller } 8034f01d4a4da7754dbe6a49cca8f94e81104acb87fJim Miller 80424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 80524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Triggers haptic feedback. 80624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 80724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private synchronized void vibrate(long duration) { 80824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (mVibrator == null) { 80924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mVibrator = (android.os.Vibrator) 81024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller getContext().getSystemService(Context.VIBRATOR_SERVICE); 81124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 81224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mVibrator.vibrate(duration); 81324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 81424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 81524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 81624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Registers a callback to be invoked when the user triggers an event. 81724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * 81824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param listener the OnDialTriggerListener to attach to this view 81924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 82024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller public void setOnTriggerListener(OnTriggerListener listener) { 82124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOnTriggerListener = listener; 82224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 82324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 82424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 82524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Dispatches a trigger event to listener. Ignored if a listener is not set. 82624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * @param whichHandle the handle that triggered the event. 82724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 82824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private void dispatchTriggerEvent(int whichHandle) { 82924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller vibrate(VIBRATE_LONG); 83024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (mOnTriggerListener != null) { 83124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOnTriggerListener.onTrigger(this, whichHandle); 83224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 83324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 83424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 83524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller /** 83624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * Sets the current grabbed state, and dispatches a grabbed state change 83724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller * event to our listener. 83824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller */ 83924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private void setGrabbedState(int newState) { 84024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (newState != mGrabbedState) { 84124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mGrabbedState = newState; 84224ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller if (mOnTriggerListener != null) { 84324ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState); 84424ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 84524ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 84624ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 84724ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller 84824ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller private void log(String msg) { 84924ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller Log.d(LOG_TAG, msg); 85024ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller } 85124ccf3c59077d81b0dd3b314822ff7dab215c165Jim Miller} 852