| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.android.wearable.watchface; |
| |
| import android.animation.AnimatorSet; |
| import android.animation.ObjectAnimator; |
| import android.app.Activity; |
| import android.content.Context; |
| import android.graphics.Color; |
| import android.os.Bundle; |
| import android.support.v7.widget.LinearLayoutManager; |
| import android.support.v7.widget.RecyclerView; |
| import android.support.wearable.view.BoxInsetLayout; |
| import android.support.wearable.view.CircledImageView; |
| import android.support.wearable.view.WearableListView; |
| import android.util.Log; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.WindowInsets; |
| import android.widget.LinearLayout; |
| import android.widget.TextView; |
| |
| import com.google.android.gms.common.ConnectionResult; |
| import com.google.android.gms.common.api.GoogleApiClient; |
| import com.google.android.gms.wearable.DataMap; |
| import com.google.android.gms.wearable.Wearable; |
| |
| /** |
| * The watch-side config activity for {@link DigitalWatchFaceService}, which allows for setting the |
| * background color. |
| */ |
| public class DigitalWatchFaceWearableConfigActivity extends Activity implements |
| WearableListView.ClickListener, WearableListView.OnScrollListener { |
| private static final String TAG = "DigitalWatchFaceConfig"; |
| |
| private GoogleApiClient mGoogleApiClient; |
| private TextView mHeader; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_digital_config); |
| |
| mHeader = (TextView) findViewById(R.id.header); |
| WearableListView listView = (WearableListView) findViewById(R.id.color_picker); |
| BoxInsetLayout content = (BoxInsetLayout) findViewById(R.id.content); |
| // BoxInsetLayout adds padding by default on round devices. Add some on square devices. |
| content.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { |
| @Override |
| public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { |
| if (!insets.isRound()) { |
| v.setPaddingRelative( |
| (int) getResources().getDimensionPixelSize(R.dimen.content_padding_start), |
| v.getPaddingTop(), |
| v.getPaddingEnd(), |
| v.getPaddingBottom()); |
| } |
| return v.onApplyWindowInsets(insets); |
| } |
| }); |
| |
| listView.setHasFixedSize(true); |
| listView.setClickListener(this); |
| listView.addOnScrollListener(this); |
| |
| String[] colors = getResources().getStringArray(R.array.color_array); |
| listView.setAdapter(new ColorListAdapter(colors)); |
| |
| mGoogleApiClient = new GoogleApiClient.Builder(this) |
| .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { |
| @Override |
| public void onConnected(Bundle connectionHint) { |
| if (Log.isLoggable(TAG, Log.DEBUG)) { |
| Log.d(TAG, "onConnected: " + connectionHint); |
| } |
| } |
| |
| @Override |
| public void onConnectionSuspended(int cause) { |
| if (Log.isLoggable(TAG, Log.DEBUG)) { |
| Log.d(TAG, "onConnectionSuspended: " + cause); |
| } |
| } |
| }) |
| .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() { |
| @Override |
| public void onConnectionFailed(ConnectionResult result) { |
| if (Log.isLoggable(TAG, Log.DEBUG)) { |
| Log.d(TAG, "onConnectionFailed: " + result); |
| } |
| } |
| }) |
| .addApi(Wearable.API) |
| .build(); |
| } |
| |
| @Override |
| protected void onStart() { |
| super.onStart(); |
| mGoogleApiClient.connect(); |
| } |
| |
| @Override |
| protected void onStop() { |
| if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) { |
| mGoogleApiClient.disconnect(); |
| } |
| super.onStop(); |
| } |
| |
| @Override // WearableListView.ClickListener |
| public void onClick(WearableListView.ViewHolder viewHolder) { |
| ColorItemViewHolder colorItemViewHolder = (ColorItemViewHolder) viewHolder; |
| updateConfigDataItem(colorItemViewHolder.mColorItem.getColor()); |
| finish(); |
| } |
| |
| @Override // WearableListView.ClickListener |
| public void onTopEmptyRegionClick() {} |
| |
| @Override // WearableListView.OnScrollListener |
| public void onScroll(int scroll) {} |
| |
| @Override // WearableListView.OnScrollListener |
| public void onAbsoluteScrollChange(int scroll) { |
| float newTranslation = Math.min(-scroll, 0); |
| mHeader.setTranslationY(newTranslation); |
| } |
| |
| @Override // WearableListView.OnScrollListener |
| public void onScrollStateChanged(int scrollState) {} |
| |
| @Override // WearableListView.OnScrollListener |
| public void onCentralPositionChanged(int centralPosition) {} |
| |
| private void updateConfigDataItem(final int backgroundColor) { |
| DataMap configKeysToOverwrite = new DataMap(); |
| configKeysToOverwrite.putInt(DigitalWatchFaceUtil.KEY_BACKGROUND_COLOR, |
| backgroundColor); |
| DigitalWatchFaceUtil.overwriteKeysInConfigDataMap(mGoogleApiClient, configKeysToOverwrite); |
| } |
| |
| private class ColorListAdapter extends WearableListView.Adapter { |
| private final String[] mColors; |
| |
| public ColorListAdapter(String[] colors) { |
| mColors = colors; |
| } |
| |
| @Override |
| public ColorItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { |
| return new ColorItemViewHolder(new ColorItem(parent.getContext())); |
| } |
| |
| @Override |
| public void onBindViewHolder(WearableListView.ViewHolder holder, int position) { |
| ColorItemViewHolder colorItemViewHolder = (ColorItemViewHolder) holder; |
| String colorName = mColors[position]; |
| colorItemViewHolder.mColorItem.setColor(colorName); |
| |
| RecyclerView.LayoutParams layoutParams = |
| new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, |
| ViewGroup.LayoutParams.WRAP_CONTENT); |
| int colorPickerItemMargin = (int) getResources() |
| .getDimension(R.dimen.digital_config_color_picker_item_margin); |
| // Add margins to first and last item to make it possible for user to tap on them. |
| if (position == 0) { |
| layoutParams.setMargins(0, colorPickerItemMargin, 0, 0); |
| } else if (position == mColors.length - 1) { |
| layoutParams.setMargins(0, 0, 0, colorPickerItemMargin); |
| } else { |
| layoutParams.setMargins(0, 0, 0, 0); |
| } |
| colorItemViewHolder.itemView.setLayoutParams(layoutParams); |
| } |
| |
| @Override |
| public int getItemCount() { |
| return mColors.length; |
| } |
| } |
| |
| /** The layout of a color item including image and label. */ |
| private static class ColorItem extends LinearLayout implements |
| WearableListView.OnCenterProximityListener { |
| /** The duration of the expand/shrink animation. */ |
| private static final int ANIMATION_DURATION_MS = 150; |
| /** The ratio for the size of a circle in shrink state. */ |
| private static final float SHRINK_CIRCLE_RATIO = .75f; |
| |
| private static final float SHRINK_LABEL_ALPHA = .5f; |
| private static final float EXPAND_LABEL_ALPHA = 1f; |
| |
| private final TextView mLabel; |
| private final CircledImageView mColor; |
| |
| private final float mExpandCircleRadius; |
| private final float mShrinkCircleRadius; |
| |
| private final ObjectAnimator mExpandCircleAnimator; |
| private final ObjectAnimator mExpandLabelAnimator; |
| private final AnimatorSet mExpandAnimator; |
| |
| private final ObjectAnimator mShrinkCircleAnimator; |
| private final ObjectAnimator mShrinkLabelAnimator; |
| private final AnimatorSet mShrinkAnimator; |
| |
| public ColorItem(Context context) { |
| super(context); |
| View.inflate(context, R.layout.color_picker_item, this); |
| |
| mLabel = (TextView) findViewById(R.id.label); |
| mColor = (CircledImageView) findViewById(R.id.color); |
| |
| mExpandCircleRadius = mColor.getCircleRadius(); |
| mShrinkCircleRadius = mExpandCircleRadius * SHRINK_CIRCLE_RATIO; |
| |
| mShrinkCircleAnimator = ObjectAnimator.ofFloat(mColor, "circleRadius", |
| mExpandCircleRadius, mShrinkCircleRadius); |
| mShrinkLabelAnimator = ObjectAnimator.ofFloat(mLabel, "alpha", |
| EXPAND_LABEL_ALPHA, SHRINK_LABEL_ALPHA); |
| mShrinkAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS); |
| mShrinkAnimator.playTogether(mShrinkCircleAnimator, mShrinkLabelAnimator); |
| |
| mExpandCircleAnimator = ObjectAnimator.ofFloat(mColor, "circleRadius", |
| mShrinkCircleRadius, mExpandCircleRadius); |
| mExpandLabelAnimator = ObjectAnimator.ofFloat(mLabel, "alpha", |
| SHRINK_LABEL_ALPHA, EXPAND_LABEL_ALPHA); |
| mExpandAnimator = new AnimatorSet().setDuration(ANIMATION_DURATION_MS); |
| mExpandAnimator.playTogether(mExpandCircleAnimator, mExpandLabelAnimator); |
| } |
| |
| @Override |
| public void onCenterPosition(boolean animate) { |
| if (animate) { |
| mShrinkAnimator.cancel(); |
| if (!mExpandAnimator.isRunning()) { |
| mExpandCircleAnimator.setFloatValues(mColor.getCircleRadius(), mExpandCircleRadius); |
| mExpandLabelAnimator.setFloatValues(mLabel.getAlpha(), EXPAND_LABEL_ALPHA); |
| mExpandAnimator.start(); |
| } |
| } else { |
| mExpandAnimator.cancel(); |
| mColor.setCircleRadius(mExpandCircleRadius); |
| mLabel.setAlpha(EXPAND_LABEL_ALPHA); |
| } |
| } |
| |
| @Override |
| public void onNonCenterPosition(boolean animate) { |
| if (animate) { |
| mExpandAnimator.cancel(); |
| if (!mShrinkAnimator.isRunning()) { |
| mShrinkCircleAnimator.setFloatValues(mColor.getCircleRadius(), mShrinkCircleRadius); |
| mShrinkLabelAnimator.setFloatValues(mLabel.getAlpha(), SHRINK_LABEL_ALPHA); |
| mShrinkAnimator.start(); |
| } |
| } else { |
| mShrinkAnimator.cancel(); |
| mColor.setCircleRadius(mShrinkCircleRadius); |
| mLabel.setAlpha(SHRINK_LABEL_ALPHA); |
| } |
| } |
| |
| private void setColor(String colorName) { |
| mLabel.setText(colorName); |
| mColor.setCircleColor(Color.parseColor(colorName)); |
| } |
| |
| private int getColor() { |
| return mColor.getDefaultCircleColor(); |
| } |
| } |
| |
| private static class ColorItemViewHolder extends WearableListView.ViewHolder { |
| private final ColorItem mColorItem; |
| |
| public ColorItemViewHolder(ColorItem colorItem) { |
| super(colorItem); |
| mColorItem = colorItem; |
| } |
| } |
| } |