mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
207 lines
6.5 KiB
Java
207 lines
6.5 KiB
Java
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.gecko.home;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.TypedArray;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.graphics.Rect;
|
|
import android.support.v4.view.ViewPager;
|
|
import android.util.AttributeSet;
|
|
import android.view.accessibility.AccessibilityEvent;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewParent;
|
|
import android.view.ViewTreeObserver;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
import android.util.Log;
|
|
|
|
import org.mozilla.gecko.home.HomePager;
|
|
import org.mozilla.gecko.R;
|
|
|
|
public class TabMenuStrip extends LinearLayout
|
|
implements HomePager.Decor,
|
|
View.OnFocusChangeListener {
|
|
private static final String LOGTAG = "GeckoTabMenuStrip";
|
|
|
|
private HomePager.OnTitleClickListener mOnTitleClickListener;
|
|
private Drawable mStrip;
|
|
private View mSelectedView;
|
|
|
|
// Data associated with the scrolling of the strip drawable.
|
|
private View toTab;
|
|
private View fromTab;
|
|
private float progress;
|
|
|
|
// This variable is used to predict the direction of scroll.
|
|
private float mPrevProgress;
|
|
|
|
public TabMenuStrip(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
|
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabMenuStrip);
|
|
final int stripResId = a.getResourceId(R.styleable.TabMenuStrip_strip, -1);
|
|
a.recycle();
|
|
|
|
if (stripResId != -1) {
|
|
mStrip = getResources().getDrawable(stripResId);
|
|
}
|
|
|
|
setWillNotDraw(false);
|
|
}
|
|
|
|
@Override
|
|
public void onAddPagerView(String title) {
|
|
final TextView button = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.tab_menu_strip, this, false);
|
|
button.setText(title.toUpperCase());
|
|
|
|
addView(button);
|
|
button.setOnClickListener(new ViewClickListener(getChildCount() - 1));
|
|
button.setOnFocusChangeListener(this);
|
|
}
|
|
|
|
@Override
|
|
public void removeAllPagerViews() {
|
|
removeAllViews();
|
|
}
|
|
|
|
@Override
|
|
public void onPageSelected(final int position) {
|
|
mSelectedView = getChildAt(position);
|
|
|
|
// Callback to measure and draw the strip after the view is visible.
|
|
ViewTreeObserver vto = mSelectedView.getViewTreeObserver();
|
|
if (vto.isAlive()) {
|
|
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
|
@Override
|
|
public void onGlobalLayout() {
|
|
mSelectedView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
|
|
|
if (mStrip != null) {
|
|
mStrip.setBounds(mSelectedView.getLeft(),
|
|
mSelectedView.getTop(),
|
|
mSelectedView.getRight(),
|
|
mSelectedView.getBottom());
|
|
}
|
|
|
|
mPrevProgress = position;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Page scroll animates the drawable and it's bounds from the previous to next child view.
|
|
@Override
|
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
|
if (mStrip == null) {
|
|
return;
|
|
}
|
|
|
|
setScrollingData(position, positionOffset);
|
|
|
|
if (fromTab == null || toTab == null) {
|
|
return;
|
|
}
|
|
|
|
final int fromTabLeft = fromTab.getLeft();
|
|
final int fromTabRight = fromTab.getRight();
|
|
|
|
final int toTabLeft = toTab.getLeft();
|
|
final int toTabRight = toTab.getRight();
|
|
|
|
mStrip.setBounds((int) (fromTabLeft + ((toTabLeft - fromTabLeft) * progress)),
|
|
0,
|
|
(int) (fromTabRight + ((toTabRight - fromTabRight) * progress)),
|
|
getHeight());
|
|
invalidate();
|
|
}
|
|
|
|
/*
|
|
* position + positionOffset goes from 0 to 2 as we scroll from page 1 to 3.
|
|
* Normalized progress is relative to the the direction the page is being scrolled towards.
|
|
* For this, we maintain direction of scroll with a state, and the child view we are moving towards and away from.
|
|
*/
|
|
private void setScrollingData(int position, float positionOffset) {
|
|
if (position >= getChildCount() - 1) {
|
|
return;
|
|
}
|
|
|
|
final float currProgress = position + positionOffset;
|
|
|
|
if (mPrevProgress > currProgress) {
|
|
toTab = getChildAt(position);
|
|
fromTab = getChildAt(position + 1);
|
|
progress = 1 - positionOffset;
|
|
} else {
|
|
toTab = getChildAt(position + 1);
|
|
fromTab = getChildAt(position);
|
|
progress = positionOffset;
|
|
}
|
|
|
|
mPrevProgress = currProgress;
|
|
}
|
|
|
|
@Override
|
|
public void onDraw(Canvas canvas) {
|
|
super.onDraw(canvas);
|
|
|
|
if (mStrip != null) {
|
|
mStrip.draw(canvas);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFocusChange(View v, boolean hasFocus) {
|
|
if (v == this && hasFocus && getChildCount() > 0) {
|
|
mSelectedView.requestFocus();
|
|
return;
|
|
}
|
|
|
|
if (!hasFocus) {
|
|
return;
|
|
}
|
|
|
|
int i = 0;
|
|
final int numTabs = getChildCount();
|
|
|
|
while (i < numTabs) {
|
|
View view = getChildAt(i);
|
|
if (view == v) {
|
|
view.requestFocus();
|
|
if (isShown()) {
|
|
// A view is focused so send an event to announce the menu strip state.
|
|
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
|
|
}
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setOnTitleClickListener(HomePager.OnTitleClickListener onTitleClickListener) {
|
|
mOnTitleClickListener = onTitleClickListener;
|
|
}
|
|
|
|
private class ViewClickListener implements OnClickListener {
|
|
private final int mIndex;
|
|
|
|
public ViewClickListener(int index) {
|
|
mIndex = index;
|
|
}
|
|
|
|
@Override
|
|
public void onClick(View view) {
|
|
if (mOnTitleClickListener != null) {
|
|
mOnTitleClickListener.onTitleClicked(mIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|