Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.launcher3.widget;
     18 
     19 import android.content.Context;
     20 import android.graphics.Canvas;
     21 import android.graphics.Color;
     22 import android.support.v7.widget.LinearLayoutManager;
     23 import android.util.AttributeSet;
     24 import android.view.View;
     25 import com.android.launcher3.BaseRecyclerView;
     26 import com.android.launcher3.model.PackageItemInfo;
     27 import com.android.launcher3.model.WidgetsModel;
     28 
     29 /**
     30  * The widgets recycler view.
     31  */
     32 public class WidgetsRecyclerView extends BaseRecyclerView {
     33 
     34     private static final String TAG = "WidgetsRecyclerView";
     35     private WidgetsModel mWidgets;
     36 
     37     public WidgetsRecyclerView(Context context) {
     38         this(context, null);
     39     }
     40 
     41     public WidgetsRecyclerView(Context context, AttributeSet attrs) {
     42         this(context, attrs, 0);
     43     }
     44 
     45     public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
     46         // API 21 and below only support 3 parameter ctor.
     47         super(context, attrs, defStyleAttr);
     48     }
     49 
     50     public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr,
     51             int defStyleRes) {
     52         this(context, attrs, defStyleAttr);
     53     }
     54 
     55     @Override
     56     protected void onFinishInflate() {
     57         super.onFinishInflate();
     58         addOnItemTouchListener(this);
     59         // create a layout manager with Launcher's context so that scroll position
     60         // can be preserved during screen rotation.
     61         setLayoutManager(new LinearLayoutManager(getContext()));
     62     }
     63 
     64     public int getFastScrollerTrackColor(int defaultTrackColor) {
     65         return Color.WHITE;
     66     }
     67 
     68     /**
     69      * Sets the widget model in this view, used to determine the fast scroll position.
     70      */
     71     public void setWidgets(WidgetsModel widgets) {
     72         mWidgets = widgets;
     73     }
     74 
     75     /**
     76      * We need to override the draw to ensure that we don't draw the overscroll effect beyond the
     77      * background bounds.
     78      */
     79     @Override
     80     protected void dispatchDraw(Canvas canvas) {
     81         canvas.clipRect(mBackgroundPadding.left, mBackgroundPadding.top,
     82                 getWidth() - mBackgroundPadding.right,
     83                 getHeight() - mBackgroundPadding.bottom);
     84         super.dispatchDraw(canvas);
     85     }
     86 
     87     /**
     88      * Maps the touch (from 0..1) to the adapter position that should be visible.
     89      */
     90     @Override
     91     public String scrollToPositionAtProgress(float touchFraction) {
     92         // Skip early if widgets are not bound.
     93         if (isModelNotReady()) {
     94             return "";
     95         }
     96 
     97         // Stop the scroller if it is scrolling
     98         stopScroll();
     99 
    100         int rowCount = mWidgets.getPackageSize();
    101         float pos = rowCount * touchFraction;
    102         int availableScrollHeight = getAvailableScrollHeight();
    103         LinearLayoutManager layoutManager = ((LinearLayoutManager) getLayoutManager());
    104         layoutManager.scrollToPositionWithOffset(0, (int) -(availableScrollHeight * touchFraction));
    105 
    106         int posInt = (int) ((touchFraction == 1)? pos -1 : pos);
    107         PackageItemInfo p = mWidgets.getPackageItemInfo(posInt);
    108         return p.titleSectionName;
    109     }
    110 
    111     /**
    112      * Updates the bounds for the scrollbar.
    113      */
    114     @Override
    115     public void onUpdateScrollbar(int dy) {
    116         // Skip early if widgets are not bound.
    117         if (isModelNotReady()) {
    118             return;
    119         }
    120 
    121         // Skip early if, there no child laid out in the container.
    122         int scrollY = getCurrentScrollY();
    123         if (scrollY < 0) {
    124             mScrollbar.setThumbOffset(-1, -1);
    125             return;
    126         }
    127 
    128         synchronizeScrollBarThumbOffsetToViewScroll(scrollY, getAvailableScrollHeight());
    129     }
    130 
    131     @Override
    132     public int getCurrentScrollY() {
    133         // Skip early if widgets are not bound.
    134         if (isModelNotReady() || getChildCount() == 0) {
    135             return -1;
    136         }
    137 
    138         View child = getChildAt(0);
    139         int rowIndex = getChildPosition(child);
    140         int y = (child.getMeasuredHeight() * rowIndex);
    141         int offset = getLayoutManager().getDecoratedTop(child);
    142 
    143         return getPaddingTop() + y - offset;
    144     }
    145 
    146     /**
    147      * Returns the available scroll height:
    148      *   AvailableScrollHeight = Total height of the all items - last page height
    149      */
    150     @Override
    151     protected int getAvailableScrollHeight() {
    152         View child = getChildAt(0);
    153         int height = child.getMeasuredHeight() * mWidgets.getPackageSize();
    154         int totalHeight = getPaddingTop() + height + getPaddingBottom();
    155         int availableScrollHeight = totalHeight - getVisibleHeight();
    156         return availableScrollHeight;
    157     }
    158 
    159     private boolean isModelNotReady() {
    160         return mWidgets == null || mWidgets.getPackageSize() == 0;
    161     }
    162 }