mobile/android/base/home/TabMenuStripLayout.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial