mobile/android/base/home/TabMenuStripLayout.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko.home;
michael@0 7
michael@0 8 import org.mozilla.gecko.R;
michael@0 9
michael@0 10 import android.content.Context;
michael@0 11 import android.content.res.TypedArray;
michael@0 12 import android.graphics.Canvas;
michael@0 13 import android.graphics.drawable.Drawable;
michael@0 14 import android.util.AttributeSet;
michael@0 15 import android.view.LayoutInflater;
michael@0 16 import android.view.View;
michael@0 17 import android.view.ViewTreeObserver;
michael@0 18 import android.view.accessibility.AccessibilityEvent;
michael@0 19 import android.widget.LinearLayout;
michael@0 20 import android.widget.TextView;
michael@0 21
michael@0 22 /**
michael@0 23 * {@code TabMenuStripLayout} is the view that draws the {@code HomePager}
michael@0 24 * tabs that are displayed in {@code TabMenuStrip}.
michael@0 25 */
michael@0 26 class TabMenuStripLayout extends LinearLayout
michael@0 27 implements View.OnFocusChangeListener {
michael@0 28
michael@0 29 private HomePager.OnTitleClickListener onTitleClickListener;
michael@0 30 private Drawable strip;
michael@0 31 private View selectedView;
michael@0 32
michael@0 33 // Data associated with the scrolling of the strip drawable.
michael@0 34 private View toTab;
michael@0 35 private View fromTab;
michael@0 36 private float progress;
michael@0 37
michael@0 38 // This variable is used to predict the direction of scroll.
michael@0 39 private float prevProgress;
michael@0 40
michael@0 41 TabMenuStripLayout(Context context, AttributeSet attrs) {
michael@0 42 super(context, attrs);
michael@0 43
michael@0 44 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabMenuStrip);
michael@0 45 final int stripResId = a.getResourceId(R.styleable.TabMenuStrip_strip, -1);
michael@0 46 a.recycle();
michael@0 47
michael@0 48 if (stripResId != -1) {
michael@0 49 strip = getResources().getDrawable(stripResId);
michael@0 50 }
michael@0 51
michael@0 52 setWillNotDraw(false);
michael@0 53 }
michael@0 54
michael@0 55 void onAddPagerView(String title) {
michael@0 56 final TextView button = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.tab_menu_strip, this, false);
michael@0 57 button.setText(title.toUpperCase());
michael@0 58
michael@0 59 addView(button);
michael@0 60 button.setOnClickListener(new ViewClickListener(getChildCount() - 1));
michael@0 61 button.setOnFocusChangeListener(this);
michael@0 62 }
michael@0 63
michael@0 64 void onPageSelected(final int position) {
michael@0 65 selectedView = getChildAt(position);
michael@0 66
michael@0 67 // Callback to measure and draw the strip after the view is visible.
michael@0 68 ViewTreeObserver vto = selectedView.getViewTreeObserver();
michael@0 69 if (vto.isAlive()) {
michael@0 70 vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
michael@0 71 @Override
michael@0 72 public void onGlobalLayout() {
michael@0 73 selectedView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
michael@0 74
michael@0 75 if (strip != null) {
michael@0 76 strip.setBounds(selectedView.getLeft(),
michael@0 77 selectedView.getTop(),
michael@0 78 selectedView.getRight(),
michael@0 79 selectedView.getBottom());
michael@0 80 }
michael@0 81
michael@0 82 prevProgress = position;
michael@0 83 }
michael@0 84 });
michael@0 85 }
michael@0 86 }
michael@0 87
michael@0 88 // Page scroll animates the drawable and its bounds from the previous to next child view.
michael@0 89 void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
michael@0 90 if (strip == null) {
michael@0 91 return;
michael@0 92 }
michael@0 93
michael@0 94 setScrollingData(position, positionOffset);
michael@0 95
michael@0 96 if (fromTab == null || toTab == null) {
michael@0 97 return;
michael@0 98 }
michael@0 99
michael@0 100 final int fromTabLeft = fromTab.getLeft();
michael@0 101 final int fromTabRight = fromTab.getRight();
michael@0 102
michael@0 103 final int toTabLeft = toTab.getLeft();
michael@0 104 final int toTabRight = toTab.getRight();
michael@0 105
michael@0 106 strip.setBounds((int) (fromTabLeft + ((toTabLeft - fromTabLeft) * progress)),
michael@0 107 0,
michael@0 108 (int) (fromTabRight + ((toTabRight - fromTabRight) * progress)),
michael@0 109 getHeight());
michael@0 110 invalidate();
michael@0 111 }
michael@0 112
michael@0 113 /*
michael@0 114 * position + positionOffset goes from 0 to 2 as we scroll from page 1 to 3.
michael@0 115 * Normalized progress is relative to the the direction the page is being scrolled towards.
michael@0 116 * For this, we maintain direction of scroll with a state, and the child view we are moving towards and away from.
michael@0 117 */
michael@0 118 void setScrollingData(int position, float positionOffset) {
michael@0 119 if (position >= getChildCount() - 1) {
michael@0 120 return;
michael@0 121 }
michael@0 122
michael@0 123 final float currProgress = position + positionOffset;
michael@0 124
michael@0 125 if (prevProgress > currProgress) {
michael@0 126 toTab = getChildAt(position);
michael@0 127 fromTab = getChildAt(position + 1);
michael@0 128 progress = 1 - positionOffset;
michael@0 129 } else {
michael@0 130 toTab = getChildAt(position + 1);
michael@0 131 fromTab = getChildAt(position);
michael@0 132 progress = positionOffset;
michael@0 133 }
michael@0 134
michael@0 135 prevProgress = currProgress;
michael@0 136 }
michael@0 137
michael@0 138 @Override
michael@0 139 public void onDraw(Canvas canvas) {
michael@0 140 super.onDraw(canvas);
michael@0 141
michael@0 142 if (strip != null) {
michael@0 143 strip.draw(canvas);
michael@0 144 }
michael@0 145 }
michael@0 146
michael@0 147 @Override
michael@0 148 public void onFocusChange(View v, boolean hasFocus) {
michael@0 149 if (v == this && hasFocus && getChildCount() > 0) {
michael@0 150 selectedView.requestFocus();
michael@0 151 return;
michael@0 152 }
michael@0 153
michael@0 154 if (!hasFocus) {
michael@0 155 return;
michael@0 156 }
michael@0 157
michael@0 158 int i = 0;
michael@0 159 final int numTabs = getChildCount();
michael@0 160
michael@0 161 while (i < numTabs) {
michael@0 162 View view = getChildAt(i);
michael@0 163 if (view == v) {
michael@0 164 view.requestFocus();
michael@0 165 if (isShown()) {
michael@0 166 // A view is focused so send an event to announce the menu strip state.
michael@0 167 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
michael@0 168 }
michael@0 169 break;
michael@0 170 }
michael@0 171
michael@0 172 i++;
michael@0 173 }
michael@0 174 }
michael@0 175
michael@0 176 void setOnTitleClickListener(HomePager.OnTitleClickListener onTitleClickListener) {
michael@0 177 this.onTitleClickListener = onTitleClickListener;
michael@0 178 }
michael@0 179
michael@0 180 private class ViewClickListener implements OnClickListener {
michael@0 181 private final int mIndex;
michael@0 182
michael@0 183 public ViewClickListener(int index) {
michael@0 184 mIndex = index;
michael@0 185 }
michael@0 186
michael@0 187 @Override
michael@0 188 public void onClick(View view) {
michael@0 189 if (onTitleClickListener != null) {
michael@0 190 onTitleClickListener.onTitleClicked(mIndex);
michael@0 191 }
michael@0 192 }
michael@0 193 }
michael@0 194 }

mercurial