close
The Wayback Machine - https://web.archive.org/web/20171110153627/https://developer.android.com/samples/WatchFace/Wearable/src/com.example.android.wearable.watchface/DigitalWatchFaceWearableConfigActivity.html
Skip to content

Most visited

Recently visited

navigation
WatchFace / Wearable / src / com.example.android.wearable.watchface /

DigitalWatchFaceWearableConfigActivity.java

1
/*
2
 * Copyright (C) 2014 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.example.android.wearable.watchface;
18
 
19
import android.animation.AnimatorSet;
20
import android.animation.ObjectAnimator;
21
import android.app.Activity;
22
import android.content.Context;
23
import android.graphics.Color;
24
import android.os.Bundle;
25
import android.support.v7.widget.LinearLayoutManager;
26
import android.support.v7.widget.RecyclerView;
27
import android.support.wearable.view.BoxInsetLayout;
28
import android.support.wearable.view.CircledImageView;
29
import android.support.wearable.view.WearableListView;
30
import android.util.Log;
31
import android.view.LayoutInflater;
32
import android.view.View;
33
import android.view.ViewGroup;
34
import android.view.WindowInsets;
35
import android.widget.LinearLayout;
36
import android.widget.TextView;
37
 
38
import com.google.android.gms.common.ConnectionResult;
39
import com.google.android.gms.common.api.GoogleApiClient;
40
import com.google.android.gms.wearable.DataMap;
41
import com.google.android.gms.wearable.Wearable;
42
 
43
/**
44
 * The watch-side config activity for {@link DigitalWatchFaceService}, which allows for setting the
45
 * background color.
46
 */
47
public class DigitalWatchFaceWearableConfigActivity extends Activity implements
48
        WearableListView.ClickListener, WearableListView.OnScrollListener {
49
    private static final String TAG = "DigitalWatchFaceConfig";
50
 
51
    private GoogleApiClient mGoogleApiClient;
52
    private TextView mHeader;
53
 
54
    @Override
55
    protected void onCreate(Bundle savedInstanceState) {
56
        super.onCreate(savedInstanceState);
57
        setContentView(R.layout.activity_digital_config);
58
 
59
        mHeader = (TextView) findViewById(R.id.header);
60
        WearableListView listView = (WearableListView) findViewById(R.id.color_picker);
61
        BoxInsetLayout content = (BoxInsetLayout) findViewById(R.id.content);
62
        // BoxInsetLayout adds padding by default on round devices. Add some on square devices.
63
        content.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
64
            @Override
65
            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
66
                if (!insets.isRound()) {
67
                    v.setPaddingRelative(
68
                            (int) getResources().getDimensionPixelSize(R.dimen.content_padding_start),
69
                            v.getPaddingTop(),
70
                            v.getPaddingEnd(),
71
                            v.getPaddingBottom());
72
                }
73
                return v.onApplyWindowInsets(insets);
74
            }
75
        });
76
 
77
        listView.setHasFixedSize(true);
78
        listView.setClickListener(this);
79
        listView.addOnScrollListener(this);
80
 
81
        String[] colors = getResources().getStringArray(R.array.color_array);
82
        listView.setAdapter(new ColorListAdapter(colors));
83
 
84
        mGoogleApiClient = new GoogleApiClient.Builder(this)
85
                .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
86
                    @Override
87
                    public void onConnected(Bundle connectionHint) {
88
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
89
                            Log.d(TAG, "onConnected: " + connectionHint);
90
                        }
91
                    }
92
 
93
                    @Override
94
                    public void onConnectionSuspended(int cause) {
95
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
96
                            Log.d(TAG, "onConnectionSuspended: " + cause);
97
                        }
98
                    }
99
                })
100
                .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
101
                    @Override
102
                    public void onConnectionFailed(ConnectionResult result) {
103
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
104
                            Log.d(TAG, "onConnectionFailed: " + result);
105
                        }
106
                    }
107
                })
108
                .addApi(Wearable.API)
109
                .build();
110
    }
111
 
112
    @Override
113
    protected void onStart() {
114
        super.onStart();
115
        mGoogleApiClient.connect();
116
    }
117
 
118
    @Override
119
    protected void onStop() {
120
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
121
            mGoogleApiClient.disconnect();
122
        }
123
        super.onStop();
124
    }
125
 
126
    @Override // WearableListView.ClickListener
127
    public void onClick(WearableListView.ViewHolder viewHolder) {
128
        ColorItemViewHolder colorItemViewHolder = (ColorItemViewHolder) viewHolder;
129
        updateConfigDataItem(colorItemViewHolder.mColorItem.getColor());
130
        finish();
131
    }
132
 
133
    @Override // WearableListView.ClickListener
134
    public void onTopEmptyRegionClick() {}
135
 
136
    @Override // WearableListView.OnScrollListener
137
    public void onScroll(int scroll) {}
138
 
139
    @Override // WearableListView.OnScrollListener
140
    public void onAbsoluteScrollChange(int scroll) {
141
        float newTranslation = Math.min(-scroll, 0);
142
        mHeader.setTranslationY(newTranslation);
143
    }
144
 
145
    @Override // WearableListView.OnScrollListener
146
    public void onScrollStateChanged(int scrollState) {}
147
 
148
    @Override // WearableListView.OnScrollListener
149
    public void onCentralPositionChanged(int centralPosition) {}
150
 
151
    private void updateConfigDataItem(final int backgroundColor) {
152
        DataMap configKeysToOverwrite = new DataMap();
153
        configKeysToOverwrite.putInt(DigitalWatchFaceUtil.KEY_BACKGROUND_COLOR,
154
                backgroundColor);
155
        DigitalWatchFaceUtil.overwriteKeysInConfigDataMap(mGoogleApiClient, configKeysToOverwrite);
156
    }
157
 
158
    private class ColorListAdapter extends WearableListView.Adapter {
159
        private final String[] mColors;
160
 
161
        public ColorListAdapter(String[] colors) {
162
            mColors = colors;
163
        }
164
 
165
        @Override
166
        public ColorItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
167
            return new ColorItemViewHolder(new ColorItem(parent.getContext()));
168
        }
169
 
170
        @Override
171
        public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
172
            ColorItemViewHolder colorItemViewHolder = (ColorItemViewHolder) holder;
173
            String colorName = mColors[position];
174
            colorItemViewHolder.mColorItem.setColor(colorName);
175
 
176
            RecyclerView.LayoutParams layoutParams =
177
                    new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
178
                            ViewGroup.LayoutParams.WRAP_CONTENT);
179
            int colorPickerItemMargin = (int) getResources()
180
                    .getDimension(R.dimen.digital_config_color_picker_item_margin);
181
            // Add margins to first and last item to make it possible for user to tap on them.
182
            if (position == 0) {
183
                layoutParams.setMargins(0, colorPickerItemMargin, 0, 0);
184
            } else if (position == mColors.length - 1) {
185
                layoutParams.setMargins(0, 0, 0, colorPickerItemMargin);
186
            } else {
187
                layoutParams.setMargins(0, 0, 0, 0);
188
            }
189
            colorItemViewHolder.itemView.setLayoutParams(layoutParams);
190
        }
191
 
192
        @Override
193
        public int getItemCount() {
194
            return mColors.length;
195
        }
196
    }
197
 
198
    /** The layout of a color item including image and label. */
199
    private static class ColorItem extends LinearLayout implements
200
            WearableListView.OnCenterProximityListener {
201
        /** The duration of the expand/shrink animation. */
202
        private static final int ANIMATION_DURATION_MS = 150;
203
        /** The ratio for the size of a circle in shrink state. */
204
        private static final float SHRINK_CIRCLE_RATIO = .75f;
205
 
206
        private static final float SHRINK_LABEL_ALPHA = .5f;
207
        private static final float EXPAND_LABEL_ALPHA = 1f;
208
 
209
        private final TextView mLabel;
210
        private final CircledImageView mColor;
211
 
212
        private final float mExpandCircleRadius;
213
        private final float mShrinkCircleRadius;
214
 
215
        private final ObjectAnimator mExpandCircleAnimator;
216
        private final ObjectAnimator mExpandLabelAnimator;
217
        private final AnimatorSet mExpandAnimator;
218
 
219
        private final ObjectAnimator mShrinkCircleAnimator;
220
        private final ObjectAnimator mShrinkLabelAnimator;
221
        private final AnimatorSet mShrinkAnimator;
222
 
223
        public ColorItem(Context context) {
224
            super(context);
225
            View.inflate(context, R.layout.color_picker_item, this);
226
 
227
            mLabel = (TextView) findViewById(R.id.label);
228
            mColor = (CircledImageView) findViewById(R.id.color);
229
 
230
            mExpandCircleRadius = mColor.getCircleRadius();
231
            mShrinkCircleRadius = mExpandCircleRadius * SHRINK_CIRCLE_RATIO;
232
 
233
            mShrinkCircleAnimator = ObjectAnimator.ofFloat(mColor, "circleRadius",
234
                    mExpandCircleRadius, mShrinkCircleRadius);
235
            mShrinkLabelAnimator = ObjectAnimator.ofFloat(mLabel, "alpha",
236
                    EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA);
237
            mShrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
238
            mShrinkAnimator.playTogether(mShrinkCircleAnimator, mShrinkLabelAnimator);
239
 
240
            mExpandCircleAnimator = ObjectAnimator.ofFloat(mColor, "circleRadius",
241
                    mShrinkCircleRadius, mExpandCircleRadius);
242
            mExpandLabelAnimator = ObjectAnimator.ofFloat(mLabel, "alpha",
243
                    SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA);
244
            mExpandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS);
245
            mExpandAnimator.playTogether(mExpandCircleAnimator, mExpandLabelAnimator);
246
        }
247
 
248
        @Override
249
        public void onCenterPosition(boolean animate) {
250
            if (animate) {
251
                mShrinkAnimator.cancel();
252
                if (!mExpandAnimator.isRunning()) {
253
                    mExpandCircleAnimator.setFloatValues(mColor.getCircleRadius(), mExpandCircleRadius);
254
                    mExpandLabelAnimator.setFloatValues(mLabel.getAlpha(), EXPAND_LABEL_ALPHA);
255
                    mExpandAnimator.start();
256
                }
257
            } else {
258
                mExpandAnimator.cancel();
259
                mColor.setCircleRadius(mExpandCircleRadius);
260
                mLabel.setAlpha(EXPAND_LABEL_ALPHA);
261
            }
262
        }
263
 
264
        @Override
265
        public void onNonCenterPosition(boolean animate) {
266
            if (animate) {
267
                mExpandAnimator.cancel();
268
                if (!mShrinkAnimator.isRunning()) {
269
                    mShrinkCircleAnimator.setFloatValues(mColor.getCircleRadius(), mShrinkCircleRadius);
270
                    mShrinkLabelAnimator.setFloatValues(mLabel.getAlpha(), SHRINK_LABEL_ALPHA);
271
                    mShrinkAnimator.start();
272
                }
273
            } else {
274
                mShrinkAnimator.cancel();
275
                mColor.setCircleRadius(mShrinkCircleRadius);
276
                mLabel.setAlpha(SHRINK_LABEL_ALPHA);
277
            }
278
        }
279
 
280
        private void setColor(String colorName) {
281
            mLabel.setText(colorName);
282
            mColor.setCircleColor(Color.parseColor(colorName));
283
        }
284
 
285
        private int getColor() {
286
            return mColor.getDefaultCircleColor();
287
        }
288
    }
289
 
290
    private static class ColorItemViewHolder extends WearableListView.ViewHolder {
291
        private final ColorItem mColorItem;
292
 
293
        public ColorItemViewHolder(ColorItem colorItem) {
294
            super(colorItem);
295
            mColorItem = colorItem;
296
        }
297
    }
298
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

BERJAYA

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)