• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.systemui.statusbar.car;
18 
19 import android.content.Context;
20 import android.content.res.TypedArray;
21 import android.database.DataSetObserver;
22 import android.graphics.Canvas;
23 import android.graphics.Paint;
24 import android.support.v4.view.PagerAdapter;
25 import android.support.v4.view.ViewPager;
26 import android.util.AttributeSet;
27 import android.util.Log;
28 import android.util.TypedValue;
29 import android.view.Gravity;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.view.ViewParent;
33 
34 import com.android.systemui.R;
35 
36 import java.lang.ref.WeakReference;
37 
38 /**
39  * Displays the dots underneath the ViewPager on the lock screen. This is really just a simplified
40  * version of PagerTitleStrip. We don't inherit from there because it's impossible to bypass some
41  * of the overriden logic in that class.
42  */
43 public class PageIndicator extends View {
44     private static final String TAG = "PageIndicator";
45     // These can be made a styleable attribute in the future if necessary.
46     private static final int SELECTED_COLOR = 0xFFF5F5F5;  // grey 100
47     private static final int UNSELECTED_COLOR = 0xFFBDBDBD;  // grey 400
48     private final PageListener mPageListener = new PageListener();
49 
50     private ViewPager mPager;
51     private WeakReference<PagerAdapter> mWatchingAdapter;
52 
53     private int mPageCount;
54     private int mCurrentPosition;
55     private Paint mPaint;
56     private int mRadius;
57     private int mStep;
58 
PageIndicator(Context context)59     public PageIndicator(Context context) {
60         super(context);
61         init();
62     }
63 
PageIndicator(Context context, AttributeSet attrs)64     public PageIndicator(Context context, AttributeSet attrs) {
65         super(context, attrs);
66         init();
67     }
68 
init()69     private void init() {
70         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
71         mPaint.setStyle(Paint.Style.FILL);
72         mRadius = getResources().getDimensionPixelSize(R.dimen.car_page_indicator_dot_diameter) / 2;
73         mStep = mRadius * 3;
74     }
75 
setupWithViewPager(ViewPager pager)76     public void setupWithViewPager(ViewPager pager) {
77         mPager = pager;
78 
79         final PagerAdapter adapter = (PagerAdapter) pager.getAdapter();
80         pager.addOnPageChangeListener(mPageListener);
81         pager.addOnAdapterChangeListener(mPageListener);
82         updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
83         invalidate();
84     }
85 
86     @Override
onDetachedFromWindow()87     protected void onDetachedFromWindow() {
88         super.onDetachedFromWindow();
89         if (mPager != null) {
90             updateAdapter(mPager.getAdapter(), null);
91             mPager.removeOnPageChangeListener(mPageListener);
92             mPager.removeOnAdapterChangeListener(mPageListener);
93             mPager = null;
94         }
95     }
96 
97     @Override
onDraw(Canvas canvas)98     protected void onDraw(Canvas canvas) {
99         super.onDraw(canvas);
100 
101         // Don't draw anything unless there's multiple pages to scroll through.  No need to clear
102         // any previous dots, since onDraw provides a canvas that's already cleared.
103         if (mPageCount <= 1)
104             return;
105 
106         int x = canvas.getWidth() / 2 - (mPageCount / 2) * mStep;
107         int y = canvas.getHeight() / 2;
108 
109         for (int i = 0; i < mPageCount; i++) {
110             if (i == mCurrentPosition) {
111                 mPaint.setColor(SELECTED_COLOR);
112             } else {
113                 mPaint.setColor(UNSELECTED_COLOR);
114             }
115 
116             canvas.drawCircle(x, y, mRadius, mPaint);
117             x += mStep;
118         }
119     }
120 
updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter)121     void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
122         if (oldAdapter != null) {
123             oldAdapter.unregisterDataSetObserver(mPageListener);
124             mWatchingAdapter = null;
125         }
126 
127         if (newAdapter != null) {
128             newAdapter.registerDataSetObserver(mPageListener);
129             mWatchingAdapter = new WeakReference<>(newAdapter);
130         }
131 
132         updateDots();
133 
134         if (mPager != null) {
135             requestLayout();
136         }
137     }
138 
getRef(WeakReference<T> weakRef)139     private <T> T getRef(WeakReference<T> weakRef) {
140         if (weakRef == null) {
141             return null;
142         }
143         return weakRef.get();
144     }
145 
updateDots()146     private void updateDots() {
147         PagerAdapter adapter = getRef(mWatchingAdapter);
148         if (adapter == null) {
149             return;
150         }
151 
152         int count = adapter.getCount();
153         if (mPageCount == count) {
154             // Nothing to be done.
155             return;
156         }
157 
158         mPageCount = count;
159         mCurrentPosition = 0;
160         invalidate();
161     }
162 
163     private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
164             ViewPager.OnAdapterChangeListener {
165 
166         @Override
onPageScrolled(int unused1, float unused2, int unused3)167         public void onPageScrolled(int unused1, float unused2, int unused3) { }
168 
169         @Override
onPageSelected(int position)170         public void onPageSelected(int position) {
171             if (mCurrentPosition == position) {
172                 return;
173             }
174 
175             if (mPageCount <= position) {
176                 Log.e(TAG, "Position out of bounds, position=" + position + " size=" + mPageCount);
177                 return;
178             }
179 
180             mCurrentPosition = position;
181             invalidate();
182         }
183 
184         @Override
onPageScrollStateChanged(int state)185         public void onPageScrollStateChanged(int state) { }
186 
187         @Override
onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter, PagerAdapter newAdapter)188         public void onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter,
189                 PagerAdapter newAdapter) {
190             updateAdapter(oldAdapter, newAdapter);
191         }
192 
193         @Override
onChanged()194         public void onChanged() {
195             updateDots();
196         }
197     }
198 }
199