Interim quick settings update.
Make existing QS panel available via pulldown from header (or keyguard status view on keyguard), update the affordances as a hint. Don't allow QS to scroll, cap to max rows. Add scrim over panel to indicate that this is purely temporary. Bug:14081801 Bug:14059974 Change-Id: I166033975cbc44b91f45ee70ea5c7540390670dd
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 685 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 623 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 893 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 940 B After Width: | Height: | Size: 537 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 939 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 812 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -14,18 +14,12 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.android.systemui.statusbar.phone.QuickSettingsScrollView
|
||||
<com.android.systemui.statusbar.phone.QuickSettingsContainerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/quick_settings_container"
|
||||
android:padding="@dimen/notification_side_padding"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/close_handle_underlap"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
>
|
||||
<com.android.systemui.statusbar.phone.QuickSettingsContainerView
|
||||
android:id="@+id/quick_settings_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:columnCount="@integer/quick_settings_num_columns"
|
||||
/>
|
||||
</com.android.systemui.statusbar.phone.QuickSettingsScrollView>
|
||||
android:background="#5f000000"
|
||||
android:animateLayoutChanges="true"
|
||||
android:columnCount="@integer/quick_settings_num_columns" />
|
||||
@@ -41,7 +41,7 @@
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="right|top"
|
||||
android:layout_marginTop="@*android:dimen/status_bar_height"
|
||||
android:layout_marginTop="@dimen/status_bar_height"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -27,14 +27,14 @@
|
||||
|
||||
<include layout="@layout/status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@*android:dimen/status_bar_height" />
|
||||
android:layout_height="@dimen/status_bar_height" />
|
||||
|
||||
<com.android.systemui.statusbar.phone.PanelHolder
|
||||
android:id="@+id/panel_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/panel_holder_padding_top"
|
||||
android:layout_marginBottom="@*android:dimen/navigation_bar_height">
|
||||
android:layout_marginBottom="@dimen/navigation_bar_height">
|
||||
<include layout="@layout/status_bar_expanded"
|
||||
android:layout_width="@dimen/notification_panel_width"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
<!-- The number of columns in the QuickSettings -->
|
||||
<integer name="quick_settings_num_columns">6</integer>
|
||||
|
||||
<!-- The maximum number of rows in the QuickSettings -->
|
||||
<integer name="quick_settings_max_rows">2</integer>
|
||||
|
||||
<!-- The number of columns that the top level tiles span in the QuickSettings -->
|
||||
<integer name="quick_settings_user_time_settings_tile_span">2</integer>
|
||||
</resources>
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
<!-- The number of columns in the QuickSettings -->
|
||||
<integer name="quick_settings_num_columns">3</integer>
|
||||
|
||||
<!-- The maximum number of rows in the QuickSettings -->
|
||||
<integer name="quick_settings_max_rows">4</integer>
|
||||
|
||||
<!-- The number of columns that the top level tiles span in the QuickSettings -->
|
||||
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
|
||||
|
||||
|
||||
@@ -81,6 +81,12 @@
|
||||
<!-- The number of columns in the QuickSettings -->
|
||||
<integer name="quick_settings_num_columns">3</integer>
|
||||
|
||||
<!-- The maximum number of rows in the QuickSettings -->
|
||||
<integer name="quick_settings_max_rows">4</integer>
|
||||
|
||||
<!-- The maximum number of rows in the QuickSettings when on the keyguard -->
|
||||
<integer name="quick_settings_max_rows_keyguard">3</integer>
|
||||
|
||||
<!-- The number of columns that the top level tiles span in the QuickSettings -->
|
||||
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
|
||||
|
||||
|
||||
@@ -269,4 +269,7 @@
|
||||
|
||||
<!-- Camera affordance drag distance -->
|
||||
<dimen name="camera_drag_distance">100dp</dimen>
|
||||
|
||||
<dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
|
||||
<dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
|
||||
</resources>
|
||||
|
||||
22
packages/SystemUI/res/values/internal.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
|
||||
<dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
|
||||
<drawable name="notification_quantum_bg">@*android:drawable/notification_quantum_bg</drawable>
|
||||
</resources>
|
||||
|
||||
@@ -30,11 +30,14 @@ public class NotificationPanelView extends PanelView {
|
||||
public static final boolean DEBUG_GESTURES = true;
|
||||
|
||||
PhoneStatusBar mStatusBar;
|
||||
private View mHeader;
|
||||
private View mKeyguardStatusView;
|
||||
|
||||
private NotificationStackScrollLayout mNotificationStackScroller;
|
||||
private int[] mTempLocation = new int[2];
|
||||
private int[] mTempChildLocation = new int[2];
|
||||
private View mNotificationParent;
|
||||
|
||||
private boolean mTrackingSettings;
|
||||
|
||||
public NotificationPanelView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -59,6 +62,8 @@ public class NotificationPanelView extends PanelView {
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mHeader = findViewById(R.id.header);
|
||||
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
|
||||
mNotificationStackScroller = (NotificationStackScrollLayout)
|
||||
findViewById(R.id.notification_stack_scroller);
|
||||
mNotificationParent = findViewById(R.id.notification_container_parent);
|
||||
@@ -98,10 +103,39 @@ public class NotificationPanelView extends PanelView {
|
||||
return mTempChildLocation[1] - mTempLocation[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||
// intercept for quick settings
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
final View target = mStatusBar.isOnKeyguard() ? mKeyguardStatusView : mHeader;
|
||||
final boolean inTarget = PhoneStatusBar.inBounds(target, event, true);
|
||||
if (inTarget && !isInSettings()) {
|
||||
mTrackingSettings = true;
|
||||
return true;
|
||||
}
|
||||
if (!inTarget && isInSettings()) {
|
||||
mTrackingSettings = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onInterceptTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
// TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
|
||||
// implementation.
|
||||
if (mTrackingSettings) {
|
||||
mStatusBar.onSettingsEvent(event);
|
||||
if (event.getAction() == MotionEvent.ACTION_UP
|
||||
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
mTrackingSettings = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (isInSettings()) {
|
||||
return true;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
@@ -97,11 +98,9 @@ import com.android.systemui.statusbar.BaseStatusBar;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.GestureRecorder;
|
||||
import com.android.systemui.statusbar.InterceptedNotifications;
|
||||
import com.android.systemui.statusbar.LatestItemView;
|
||||
import com.android.systemui.statusbar.NotificationData;
|
||||
import com.android.systemui.statusbar.NotificationData.Entry;
|
||||
import com.android.systemui.statusbar.NotificationOverflowContainer;
|
||||
import com.android.systemui.statusbar.NotificationOverflowIconsView;
|
||||
import com.android.systemui.statusbar.SignalClusterView;
|
||||
import com.android.systemui.statusbar.StatusBarIconView;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
@@ -233,8 +232,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
int mKeyguardMaxNotificationCount;
|
||||
View mDateTimeView;
|
||||
View mClearButton;
|
||||
ImageView mSettingsButton, mNotificationButton;
|
||||
View mKeyguardSettingsFlipButton;
|
||||
FlipperButton mHeaderFlipper, mKeyguardFlipper;
|
||||
|
||||
// carrier/wifi label
|
||||
private TextView mCarrierLabel;
|
||||
@@ -314,9 +312,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " +
|
||||
"selfChange=%s userSetup=%s mUserSetup=%s",
|
||||
selfChange, userSetup, mUserSetup));
|
||||
if (mSettingsButton != null && mHasFlipSettings) {
|
||||
mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
mHeaderFlipper.userSetup(userSetup);
|
||||
mKeyguardFlipper.userSetup(userSetup);
|
||||
|
||||
if (mSettingsPanel != null) {
|
||||
mSettingsPanel.setEnabled(userSetup);
|
||||
}
|
||||
@@ -371,6 +369,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
|
||||
private Runnable mOnFlipRunnable;
|
||||
private InterceptedNotifications mIntercepted;
|
||||
private VelocityTracker mSettingsTracker;
|
||||
private float mSettingsDownY;
|
||||
private boolean mSettingsCancelled;
|
||||
private boolean mSettingsClosing;
|
||||
private int mNotificationPadding;
|
||||
|
||||
private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
|
||||
new OnChildLocationsChangedListener() {
|
||||
@@ -631,35 +634,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
mDateTimeView.setEnabled(true);
|
||||
}
|
||||
|
||||
mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
|
||||
if (mSettingsButton != null) {
|
||||
mSettingsButton.setOnClickListener(mSettingsButtonListener);
|
||||
if (mHasSettingsPanel) {
|
||||
if (mStatusBarView.hasFullWidthNotifications()) {
|
||||
// the settings panel is hiding behind this button
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// there is a settings panel, but it's on the other side of the (large) screen
|
||||
final View buttonHolder = mStatusBarWindow.findViewById(
|
||||
R.id.settings_button_holder);
|
||||
if (buttonHolder != null) {
|
||||
buttonHolder.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no settings panel, go straight to settings
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
|
||||
}
|
||||
}
|
||||
if (mHasFlipSettings) {
|
||||
mNotificationButton = (ImageView) mStatusBarWindow.findViewById(
|
||||
R.id.notification_button);
|
||||
if (mNotificationButton != null) {
|
||||
mNotificationButton.setOnClickListener(mNotificationButtonListener);
|
||||
}
|
||||
}
|
||||
mHeaderFlipper = new FlipperButton(mNotificationPanelHeader
|
||||
.findViewById(R.id.settings_button_holder));
|
||||
ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
|
||||
mKeyguardFlipper = new FlipperButton(flipStub.inflate());
|
||||
|
||||
if (!mNotificationPanelIsFullScreenWidth) {
|
||||
mNotificationPanel.setSystemUiVisibility(
|
||||
@@ -735,6 +713,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
}
|
||||
|
||||
// Quick Settings (where available, some restrictions apply)
|
||||
mNotificationPadding = mContext.getResources()
|
||||
.getDimensionPixelSize(R.dimen.notification_side_padding);
|
||||
if (mHasSettingsPanel) {
|
||||
// first, figure out where quick settings should be inflated
|
||||
final View settings_stub;
|
||||
@@ -803,6 +783,87 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
return mStatusBarView;
|
||||
}
|
||||
|
||||
public boolean onSettingsEvent(MotionEvent event) {
|
||||
if (mSettingsTracker != null) {
|
||||
mSettingsTracker.addMovement(event);
|
||||
}
|
||||
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
mSettingsTracker = VelocityTracker.obtain();
|
||||
mSettingsDownY = event.getY();
|
||||
mSettingsCancelled = false;
|
||||
mSettingsClosing = mFlipSettingsView.getVisibility() == View.VISIBLE;
|
||||
mFlipSettingsView.setVisibility(View.VISIBLE);
|
||||
mStackScroller.setVisibility(View.VISIBLE);
|
||||
positionSettings(0);
|
||||
if (!mSettingsClosing) {
|
||||
mFlipSettingsView.setTranslationY(-mNotificationPanel.getMeasuredHeight());
|
||||
}
|
||||
dispatchSettingsEvent(event);
|
||||
} else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP
|
||||
|| event.getAction() == MotionEvent.ACTION_CANCEL)) {
|
||||
final float dy = event.getY() - mSettingsDownY;
|
||||
final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper;
|
||||
final boolean inButton = flipper.inHolderBounds(event);
|
||||
final int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||
final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop;
|
||||
if (!qsTap && !inButton) {
|
||||
mSettingsTracker.computeCurrentVelocity(1000);
|
||||
final float vy = mSettingsTracker.getYVelocity();
|
||||
if (dy <= slop || vy <= 0) {
|
||||
flipToNotifications();
|
||||
} else {
|
||||
flipToSettings();
|
||||
}
|
||||
}
|
||||
mSettingsTracker.recycle();
|
||||
mSettingsTracker = null;
|
||||
dispatchSettingsEvent(event);
|
||||
} else if (mSettingsTracker != null && event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
final float dy = event.getY() - mSettingsDownY;
|
||||
positionSettings(dy);
|
||||
if (mSettingsClosing) {
|
||||
final boolean qsTap =
|
||||
Math.abs(dy) < ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||
if (!mSettingsCancelled && !qsTap) {
|
||||
MotionEvent cancelEvent = MotionEvent.obtainNoHistory(event);
|
||||
cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
|
||||
dispatchSettingsEvent(cancelEvent);
|
||||
mSettingsCancelled = true;
|
||||
}
|
||||
} else {
|
||||
dispatchSettingsEvent(event);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void dispatchSettingsEvent(MotionEvent event) {
|
||||
final View target = mSettingsClosing ? mFlipSettingsView : mNotificationPanelHeader;
|
||||
final int[] targetLoc = new int[2];
|
||||
target.getLocationInWindow(targetLoc);
|
||||
final int[] panelLoc = new int[2];
|
||||
mNotificationPanel.getLocationInWindow(panelLoc);
|
||||
final int dx = targetLoc[0] - panelLoc[0];
|
||||
final int dy = targetLoc[1] - panelLoc[1];
|
||||
event.offsetLocation(-dx, -dy);
|
||||
target.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
private void positionSettings(float dy) {
|
||||
final int h = mFlipSettingsView.getMeasuredHeight();
|
||||
final int ph = mNotificationPanel.getMeasuredHeight();
|
||||
if (mSettingsClosing) {
|
||||
dy = Math.min(Math.max(-ph, dy), 0);
|
||||
mFlipSettingsView.setTranslationY(dy);
|
||||
mStackScroller.setTranslationY(ph + dy);
|
||||
} else {
|
||||
dy = Math.min(Math.max(0, dy), ph);
|
||||
mFlipSettingsView.setTranslationY(-h + dy - mNotificationPadding * 2);
|
||||
mStackScroller.setTranslationY(dy);
|
||||
}
|
||||
}
|
||||
|
||||
private void startKeyguard() {
|
||||
KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
|
||||
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
|
||||
@@ -1163,17 +1224,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear);
|
||||
}
|
||||
|
||||
if (mSettingsButton != null) {
|
||||
// Force asset reloading
|
||||
mSettingsButton.setImageDrawable(null);
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
|
||||
}
|
||||
|
||||
if (mNotificationButton != null) {
|
||||
// Force asset reloading
|
||||
mNotificationButton.setImageDrawable(null);
|
||||
mNotificationButton.setImageResource(R.drawable.ic_notifications);
|
||||
}
|
||||
mHeaderFlipper.refreshLayout();
|
||||
mKeyguardFlipper.refreshLayout();
|
||||
|
||||
refreshAllStatusBarIcons();
|
||||
}
|
||||
@@ -1228,9 +1280,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
}
|
||||
}
|
||||
|
||||
if (mSettingsButton != null) {
|
||||
mSettingsButton.setEnabled(isDeviceProvisioned());
|
||||
}
|
||||
mHeaderFlipper.provisionCheck(provisioned);
|
||||
mKeyguardFlipper.provisionCheck(provisioned);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1647,6 +1698,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
|
||||
mStatusBarWindow.cancelExpandHelper();
|
||||
mStatusBarView.collapseAllPanels(true);
|
||||
if (isFlippedToSettings()) {
|
||||
flipToNotifications();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1694,8 +1748,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
final int FLIP_DURATION_IN = 225;
|
||||
final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT);
|
||||
|
||||
Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim,
|
||||
mSettingsButtonAnim, mClearButtonAnim;
|
||||
Animator mScrollViewAnim, mFlipSettingsViewAnim, mClearButtonAnim;
|
||||
|
||||
@Override
|
||||
public void animateExpandNotificationsPanel() {
|
||||
@@ -1715,33 +1768,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
public void flipToNotifications() {
|
||||
if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
|
||||
if (mScrollViewAnim != null) mScrollViewAnim.cancel();
|
||||
if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
|
||||
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
|
||||
mHeaderFlipper.cancel();
|
||||
mKeyguardFlipper.cancel();
|
||||
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
|
||||
|
||||
mStackScroller.setVisibility(View.VISIBLE);
|
||||
final int h = mNotificationPanel.getMeasuredHeight();
|
||||
final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0;
|
||||
final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h;
|
||||
mScrollViewAnim = start(
|
||||
startDelay(FLIP_DURATION_OUT,
|
||||
startDelay(0,
|
||||
interpolator(mDecelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f)
|
||||
.setDuration(FLIP_DURATION_IN)
|
||||
ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0)
|
||||
.setDuration(FLIP_DURATION)
|
||||
)));
|
||||
mFlipSettingsViewAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
interpolator(mAccelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
|
||||
interpolator(mDecelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h)
|
||||
)
|
||||
.setDuration(FLIP_DURATION_OUT),
|
||||
mFlipSettingsView, View.INVISIBLE));
|
||||
mNotificationButtonAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
|
||||
.setDuration(FLIP_DURATION),
|
||||
mNotificationButton, View.INVISIBLE));
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mSettingsButtonAnim = start(
|
||||
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
|
||||
.setDuration(FLIP_DURATION));
|
||||
mFlipSettingsView, View.INVISIBLE));
|
||||
mHeaderFlipper.flipToNotifications();
|
||||
mKeyguardFlipper.flipToNotifications();
|
||||
mClearButton.setVisibility(View.VISIBLE);
|
||||
mClearButton.setAlpha(0f);
|
||||
setAreThereNotifications(); // this will show/hide the button as necessary
|
||||
@@ -1767,7 +1816,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
|
||||
if (mHasFlipSettings) {
|
||||
mNotificationPanel.expand();
|
||||
if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
|
||||
if (mFlipSettingsView.getVisibility() != View.VISIBLE
|
||||
|| mFlipSettingsView.getTranslationY() < 0) {
|
||||
flipToSettings();
|
||||
}
|
||||
} else if (mSettingsPanel != null) {
|
||||
@@ -1777,23 +1827,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
if (false) postStartTracing();
|
||||
}
|
||||
|
||||
public void switchToSettings() {
|
||||
// Settings are not available in setup
|
||||
if (!mUserSetup) return;
|
||||
|
||||
mFlipSettingsView.setScaleX(1f);
|
||||
mFlipSettingsView.setVisibility(View.VISIBLE);
|
||||
mSettingsButton.setVisibility(View.GONE);
|
||||
mStackScroller.setVisibility(View.GONE);
|
||||
mStackScroller.setScaleX(0f);
|
||||
mNotificationButton.setVisibility(View.VISIBLE);
|
||||
mNotificationButton.setAlpha(1f);
|
||||
mClearButton.setVisibility(View.GONE);
|
||||
if (mOnFlipRunnable != null) {
|
||||
mOnFlipRunnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlippedToSettings() {
|
||||
if (mFlipSettingsView != null) {
|
||||
return mFlipSettingsView.getVisibility() == View.VISIBLE;
|
||||
@@ -1807,34 +1840,29 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
|
||||
if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
|
||||
if (mScrollViewAnim != null) mScrollViewAnim.cancel();
|
||||
if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
|
||||
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
|
||||
mHeaderFlipper.cancel();
|
||||
mKeyguardFlipper.cancel();
|
||||
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
|
||||
|
||||
mFlipSettingsView.setVisibility(View.VISIBLE);
|
||||
mFlipSettingsView.setScaleX(0f);
|
||||
final int h = mNotificationPanel.getMeasuredHeight();
|
||||
final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h;
|
||||
final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0;
|
||||
mFlipSettingsViewAnim = start(
|
||||
startDelay(FLIP_DURATION_OUT,
|
||||
interpolator(mDecelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
|
||||
.setDuration(FLIP_DURATION_IN)
|
||||
)));
|
||||
startDelay(0,
|
||||
interpolator(mDecelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, 0f)
|
||||
.setDuration(FLIP_DURATION)
|
||||
)));
|
||||
mScrollViewAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
interpolator(mAccelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f)
|
||||
interpolator(mDecelerateInterpolator,
|
||||
ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h)
|
||||
)
|
||||
.setDuration(FLIP_DURATION_OUT),
|
||||
mStackScroller, View.INVISIBLE));
|
||||
mSettingsButtonAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
|
||||
.setDuration(FLIP_DURATION),
|
||||
mStackScroller, View.INVISIBLE));
|
||||
mNotificationButton.setVisibility(View.VISIBLE);
|
||||
mNotificationButtonAnim = start(
|
||||
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
|
||||
.setDuration(FLIP_DURATION));
|
||||
mHeaderFlipper.flipToSettings();
|
||||
mKeyguardFlipper.flipToSettings();
|
||||
mClearButtonAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
|
||||
@@ -1883,18 +1911,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
// reset things to their proper state
|
||||
if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
|
||||
if (mScrollViewAnim != null) mScrollViewAnim.cancel();
|
||||
if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
|
||||
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
|
||||
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
|
||||
|
||||
mStackScroller.setScaleX(1f);
|
||||
mStackScroller.setVisibility(View.VISIBLE);
|
||||
mSettingsButton.setAlpha(1f);
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mNotificationPanel.setVisibility(View.GONE);
|
||||
mFlipSettingsView.setVisibility(View.GONE);
|
||||
mNotificationButton.setVisibility(View.GONE);
|
||||
|
||||
setAreThereNotifications(); // show the clear button
|
||||
|
||||
mHeaderFlipper.reset();
|
||||
mKeyguardFlipper.reset();
|
||||
}
|
||||
|
||||
mExpandedVisible = false;
|
||||
@@ -2947,15 +2973,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
}
|
||||
mKeyguardStatusView.setVisibility(View.VISIBLE);
|
||||
mNotificationPanelHeader.setVisibility(View.GONE);
|
||||
if (mKeyguardSettingsFlipButton == null) {
|
||||
ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
|
||||
mKeyguardSettingsFlipButton = flipStub.inflate();
|
||||
installSettingsButton(mKeyguardSettingsFlipButton);
|
||||
}
|
||||
mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE);
|
||||
mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE);
|
||||
mKeyguardSettingsFlipButton.findViewById(R.id.notification_button)
|
||||
.setVisibility(View.INVISIBLE);
|
||||
|
||||
mKeyguardFlipper.setVisibility(View.VISIBLE);
|
||||
mSettingsContainer.setKeyguardShowing(true);
|
||||
updateRowStates();
|
||||
}
|
||||
|
||||
@@ -2963,9 +2983,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
mOnKeyguard = false;
|
||||
mKeyguardStatusView.setVisibility(View.GONE);
|
||||
mNotificationPanelHeader.setVisibility(View.VISIBLE);
|
||||
if (mKeyguardSettingsFlipButton != null) {
|
||||
mKeyguardSettingsFlipButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
mKeyguardFlipper.setVisibility(View.GONE);
|
||||
mSettingsContainer.setKeyguardShowing(false);
|
||||
updateRowStates();
|
||||
instantCollapseNotificationPanel();
|
||||
}
|
||||
@@ -3030,39 +3050,112 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
|
||||
}
|
||||
}
|
||||
|
||||
private void installSettingsButton(View parent) {
|
||||
final ImageView settingsButton =
|
||||
(ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
|
||||
final ImageView notificationButton =
|
||||
(ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
|
||||
if (settingsButton != null) {
|
||||
settingsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
animateExpandSettingsPanel();
|
||||
v.setVisibility(View.INVISIBLE);
|
||||
notificationButton.setVisibility(View.VISIBLE);
|
||||
public static boolean inBounds(View view, MotionEvent event, boolean orAbove) {
|
||||
final int[] location = new int[2];
|
||||
view.getLocationInWindow(location);
|
||||
final int rx = (int) event.getRawX();
|
||||
final int ry = (int) event.getRawY();
|
||||
return rx >= location[0] && rx <= location[0] + view.getMeasuredWidth()
|
||||
&& (orAbove || ry >= location[1]) && ry <= location[1] + view.getMeasuredHeight();
|
||||
}
|
||||
|
||||
private final class FlipperButton {
|
||||
private final View mHolder;
|
||||
|
||||
private ImageView mSettingsButton, mNotificationButton;
|
||||
private Animator mSettingsButtonAnim, mNotificationButtonAnim;
|
||||
|
||||
public FlipperButton(View holder) {
|
||||
mHolder = holder;
|
||||
mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button);
|
||||
if (mSettingsButton != null) {
|
||||
mSettingsButton.setOnClickListener(mSettingsButtonListener);
|
||||
if (mHasSettingsPanel) {
|
||||
// the settings panel is hiding behind this button
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// no settings panel, go straight to settings
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
|
||||
}
|
||||
}
|
||||
if (mHasFlipSettings) {
|
||||
mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button);
|
||||
if (mNotificationButton != null) {
|
||||
mNotificationButton.setOnClickListener(mNotificationButtonListener);
|
||||
}
|
||||
});
|
||||
settingsButton.setVisibility(View.VISIBLE);
|
||||
if (mHasSettingsPanel) {
|
||||
// the settings panel is hiding behind this button
|
||||
settingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
|
||||
} else {
|
||||
// no settings panel, go straight to settings
|
||||
settingsButton.setImageResource(R.drawable.ic_notify_settings);
|
||||
}
|
||||
}
|
||||
if (notificationButton != null) {
|
||||
notificationButton.setVisibility(View.INVISIBLE);
|
||||
notificationButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
flipToNotifications();
|
||||
v.setVisibility(View.INVISIBLE);
|
||||
settingsButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
public boolean inHolderBounds(MotionEvent event) {
|
||||
return inBounds(mHolder, event, false);
|
||||
}
|
||||
|
||||
public void provisionCheck(boolean provisioned) {
|
||||
if (mSettingsButton != null) {
|
||||
mSettingsButton.setEnabled(provisioned);
|
||||
}
|
||||
}
|
||||
|
||||
public void userSetup(boolean userSetup) {
|
||||
if (mSettingsButton != null && mHasFlipSettings) {
|
||||
mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
cancel();
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mNotificationButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void refreshLayout() {
|
||||
if (mSettingsButton != null) {
|
||||
// Force asset reloading
|
||||
mSettingsButton.setImageDrawable(null);
|
||||
mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
|
||||
}
|
||||
|
||||
if (mNotificationButton != null) {
|
||||
// Force asset reloading
|
||||
mNotificationButton.setImageDrawable(null);
|
||||
mNotificationButton.setImageResource(R.drawable.ic_notifications);
|
||||
}
|
||||
}
|
||||
|
||||
public void flipToSettings() {
|
||||
mSettingsButtonAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
|
||||
.setDuration(FLIP_DURATION),
|
||||
mStackScroller, View.INVISIBLE));
|
||||
mNotificationButton.setVisibility(View.VISIBLE);
|
||||
mNotificationButtonAnim = start(
|
||||
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
|
||||
.setDuration(FLIP_DURATION));
|
||||
}
|
||||
|
||||
public void flipToNotifications() {
|
||||
mNotificationButtonAnim = start(
|
||||
setVisibilityWhenDone(
|
||||
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
|
||||
.setDuration(FLIP_DURATION),
|
||||
mNotificationButton, View.INVISIBLE));
|
||||
|
||||
mSettingsButton.setVisibility(View.VISIBLE);
|
||||
mSettingsButtonAnim = start(
|
||||
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
|
||||
.setDuration(FLIP_DURATION));
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
|
||||
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
|
||||
}
|
||||
|
||||
public void setVisibility(int vis) {
|
||||
mHolder.setVisibility(vis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,13 @@ package com.android.systemui.statusbar.phone;
|
||||
import android.animation.LayoutTransition;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -31,30 +37,58 @@ import com.android.systemui.R;
|
||||
*/
|
||||
class QuickSettingsContainerView extends FrameLayout {
|
||||
|
||||
private static boolean sShowScrim = true;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
// The number of columns in the QuickSettings grid
|
||||
private int mNumColumns;
|
||||
|
||||
private boolean mKeyguardShowing;
|
||||
private int mMaxRows;
|
||||
private int mMaxRowsOnKeyguard;
|
||||
|
||||
// The gap between tiles in the QuickSettings grid
|
||||
private float mCellGap;
|
||||
|
||||
private ScrimView mScrim;
|
||||
|
||||
public QuickSettingsContainerView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
mContext = context;
|
||||
updateResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mScrim = new ScrimView(mContext);
|
||||
addView(mScrim);
|
||||
mScrim.setAlpha(sShowScrim ? 1 : 0);
|
||||
// TODO: Setup the layout transitions
|
||||
LayoutTransition transitions = getLayoutTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (mScrim.getAlpha() == 1) {
|
||||
mScrim.animate().alpha(0).setDuration(1000).start();
|
||||
sShowScrim = false;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
void updateResources() {
|
||||
Resources r = getContext().getResources();
|
||||
mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap);
|
||||
mNumColumns = r.getInteger(R.integer.quick_settings_num_columns);
|
||||
mMaxRows = r.getInteger(R.integer.quick_settings_max_rows);
|
||||
mMaxRowsOnKeyguard = r.getInteger(R.integer.quick_settings_max_rows_keyguard);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
void setKeyguardShowing(boolean showing) {
|
||||
mKeyguardShowing = showing;
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@@ -71,10 +105,18 @@ class QuickSettingsContainerView extends FrameLayout {
|
||||
final int N = getChildCount();
|
||||
int cellHeight = 0;
|
||||
int cursor = 0;
|
||||
int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (getChildAt(i).equals(mScrim)) {
|
||||
continue;
|
||||
}
|
||||
// Update the child's width
|
||||
QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
|
||||
if (v.getVisibility() != View.GONE) {
|
||||
int row = (int) (cursor / mNumColumns);
|
||||
if (row >= maxRows) continue;
|
||||
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
|
||||
int colSpan = v.getColumnSpan();
|
||||
lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap);
|
||||
@@ -102,6 +144,7 @@ class QuickSettingsContainerView extends FrameLayout {
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
mScrim.bringToFront();
|
||||
final int N = getChildCount();
|
||||
final boolean isLayoutRtl = isLayoutRtl();
|
||||
final int width = getWidth();
|
||||
@@ -109,8 +152,18 @@ class QuickSettingsContainerView extends FrameLayout {
|
||||
int x = getPaddingStart();
|
||||
int y = getPaddingTop();
|
||||
int cursor = 0;
|
||||
int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (getChildAt(i).equals(mScrim)) {
|
||||
int w = right - left - getPaddingLeft() - getPaddingRight();
|
||||
int h = bottom - top - getPaddingTop() - getPaddingBottom();
|
||||
mScrim.measure(
|
||||
MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
|
||||
mScrim.layout(getPaddingLeft(), getPaddingTop(), right, bottom);
|
||||
continue;
|
||||
}
|
||||
QuickSettingsTileView child = (QuickSettingsTileView) getChildAt(i);
|
||||
ViewGroup.LayoutParams lp = child.getLayoutParams();
|
||||
if (child.getVisibility() != GONE) {
|
||||
@@ -121,6 +174,7 @@ class QuickSettingsContainerView extends FrameLayout {
|
||||
final int childHeight = lp.height;
|
||||
|
||||
int row = (int) (cursor / mNumColumns);
|
||||
if (row >= maxRows) continue;
|
||||
|
||||
// Push the item to the next row if it can't fit on this one
|
||||
if ((col + colSpan) > mNumColumns) {
|
||||
@@ -150,4 +204,87 @@ class QuickSettingsContainerView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ScrimView extends View {
|
||||
private static final int COLOR = 0xaf4285f4;
|
||||
|
||||
private final Paint mLinePaint;
|
||||
private final int mStrokeWidth;
|
||||
private final Rect mTmp = new Rect();
|
||||
private final Paint mTextPaint;
|
||||
private final int mTextSize;
|
||||
|
||||
public ScrimView(Context context) {
|
||||
super(context);
|
||||
setFocusable(false);
|
||||
final Resources res = context.getResources();
|
||||
mStrokeWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_stroke_width);
|
||||
mTextSize = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_text_size);
|
||||
|
||||
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mLinePaint.setColor(COLOR);
|
||||
mLinePaint.setStrokeWidth(mStrokeWidth);
|
||||
mLinePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
mLinePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
mLinePaint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mTextPaint.setColor(COLOR);
|
||||
mTextPaint.setTextSize(mTextSize);
|
||||
mTextPaint.setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
final int w = getMeasuredWidth();
|
||||
final int h = getMeasuredHeight();
|
||||
final int f = mStrokeWidth * 3 / 4;
|
||||
|
||||
canvas.drawPath(line(f, h / 2, w - f, h / 2), mLinePaint);
|
||||
canvas.drawPath(line(w / 2, f, w / 2, h - f), mLinePaint);
|
||||
|
||||
final int s = mStrokeWidth;
|
||||
mTextPaint.setTextAlign(Paint.Align.RIGHT);
|
||||
canvas.drawText("FUTURE", w / 2 - s, h / 2 - s, mTextPaint);
|
||||
mTextPaint.setTextAlign(Paint.Align.LEFT);
|
||||
canvas.drawText("SITE OF", w / 2 + s, h / 2 - s , mTextPaint);
|
||||
mTextPaint.setTextAlign(Paint.Align.RIGHT);
|
||||
drawUnder(canvas, "QUANTUM", w / 2 - s, h / 2 + s);
|
||||
mTextPaint.setTextAlign(Paint.Align.LEFT);
|
||||
drawUnder(canvas, "SETTINGS", w / 2 + s, h / 2 + s);
|
||||
}
|
||||
|
||||
private void drawUnder(Canvas c, String text, float x, float y) {
|
||||
if (mTmp.isEmpty()) {
|
||||
mTextPaint.getTextBounds(text, 0, text.length(), mTmp);
|
||||
}
|
||||
c.drawText(text, x, y + mTmp.height() * .85f, mTextPaint);
|
||||
}
|
||||
|
||||
private Path line(float x1, float y1, float x2, float y2) {
|
||||
final int a = mStrokeWidth * 2;
|
||||
final Path p = new Path();
|
||||
p.moveTo(x1, y1);
|
||||
p.lineTo(x2, y2);
|
||||
if (y1 == y2) {
|
||||
p.moveTo(x1 + a, y1 + a);
|
||||
p.lineTo(x1, y1);
|
||||
p.lineTo(x1 + a, y1 - a);
|
||||
|
||||
p.moveTo(x2 - a, y2 - a);
|
||||
p.lineTo(x2, y2);
|
||||
p.lineTo(x2 - a, y2 + a);
|
||||
}
|
||||
if (x1 == x2) {
|
||||
p.moveTo(x1 - a, y1 + a);
|
||||
p.lineTo(x1, y1);
|
||||
p.lineTo(x1 + a, y1 + a);
|
||||
|
||||
p.moveTo(x2 - a, y2 - a);
|
||||
p.lineTo(x2, y2);
|
||||
p.lineTo(x2 + a, y2 - a);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||