/* * Copyright (C) 2016 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.android.car.cluster.sample.cards; import android.animation.TimeInterpolator; import android.content.Context; import android.graphics.BitmapFactory; import android.util.Log; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.Chronometer; import android.widget.LinearLayout; import android.widget.TextView; import com.android.car.cluster.sample.DebugUtil; import com.android.car.cluster.sample.R; /** * Card responsible to display current call status. */ public class CallCard extends CardView { private final static String TAG = DebugUtil.getTag(CallCard.class); private LinearLayout mPhonePanel; private Chronometer mCallDuration; private TextView mContactName; private TextView mCallStatusTextView; private LinearLayout mCallDurationPanel; private int mIncomingCallTextHeight; private int mCallDurationTextHeight; public int getCallStatus() { return mCallStatus; } public @interface CallStatus { int INCOMING_OR_DIALING = 1; int ACTIVE = 2; int DISCONNECTED = 4; } @CallStatus private int mCallStatus; public CallCard(Context context, PriorityChangedListener listener) { super(context, CardType.PHONE_CALL, listener); } @Override protected void init() { if (DebugUtil.DEBUG) { Log.d(TAG, "init"); } mCallStatus = CallStatus.INCOMING_OR_DIALING; mPriority = PRIORITY_CALL_INCOMING; inflate(R.layout.call_card); mPhonePanel = viewById(R.id.phone_text_panel); mCallStatusTextView = viewById(R.id.call_status); mCallDuration = viewById(R.id.call_duration); mContactName = viewById(R.id.contact_name); mCallDurationPanel = viewById(R.id.call_duration_panel); mDetailsPanel = mPhonePanel; mLeftIconSwitcher.setVisibility(GONE); mCallDurationPanel.setVisibility(INVISIBLE); setRightIcon( BitmapFactory.decodeResource(getResources(), R.drawable.phone), true); final ViewTreeObserver observer = mPhonePanel.getViewTreeObserver(); // Make sure to get dimensions after layout has been created. observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mPhonePanel.getViewTreeObserver().removeOnGlobalLayoutListener(this); mIncomingCallTextHeight = mCallStatusTextView.getHeight(); mCallDurationTextHeight = mCallDuration.getHeight(); // Call duration is hidden when call is not answered, adjust panel Y pos. mPhonePanel.setTranslationY(mCallDurationTextHeight / 2); } }); } public void setContactName(String contactName) { mContactName.setText(contactName); } public void setStatusLabel(String status) { mCallStatusTextView.setText(status); } public void animateCallConnected(long connectedTimestamp) { if (DebugUtil.DEBUG) { Log.d(TAG, "animateCallConnected, current status: " + mCallStatus); } if (mCallStatus == CallStatus.INCOMING_OR_DIALING) { mCallStatus = CallStatus.ACTIVE; // Decrease priority after call is answered. runDelayed(3000, new Runnable() { @Override public void run() { setPriority(PRIORITY_CALL_ACTIVE); } }); final long duration = 500 * DebugUtil.ANIMATION_FACTOR; TimeInterpolator interpolator = new AccelerateDecelerateInterpolator(getContext(), null); mCallDuration.setBase(connectedTimestamp); mCallDuration.start(); mBackgroundImage.animate() .alpha(0f) .setDuration(duration); mLeftIconSwitcher.setTranslationX(mLeftPadding); mLeftIconSwitcher.setVisibility(VISIBLE); mRightIconSwitcher.animate() .translationX(mLeftPadding + mIconsOverlap) .setInterpolator(interpolator) .setDuration(duration); setRightIcon( BitmapFactory.decodeResource(getResources(), R.drawable.phone_active), true); mDetailsPanel.animate() .translationX( mLeftPadding + mIconsOverlap + mIconSize + mLeftPadding) .setInterpolator(interpolator) .setDuration(duration); mCallStatusTextView.animate() .alpha(0f) .setDuration(duration); mCallDurationPanel.setAlpha(0); mCallDurationPanel.setVisibility(VISIBLE); mCallDurationPanel.animate() .setDuration(duration) .alpha(1); mPhonePanel.animate() .translationYBy(-(mIncomingCallTextHeight + mCallDurationTextHeight) / 2) .setDuration(duration); } } public void animateCallDisconnected() { if (DebugUtil.DEBUG) { Log.d(TAG, "animateCallConnected, current status: " + mCallStatus); } if (mCallStatus == CallStatus.ACTIVE) { mCallStatus = CallStatus.DISCONNECTED; runDelayed(2000, new Runnable() { @Override public void run() { setPriority(PRIORITY_GARBAGE); } }); mCallDuration.stop(); final int duration = 500; TimeInterpolator interpolator = new AccelerateDecelerateInterpolator(getContext(), null); setRightIcon( BitmapFactory.decodeResource(getResources(), R.drawable.phone), true); mRightIconSwitcher.animate() .translationX(mLeftPadding) .setInterpolator(interpolator) .setDuration(duration * DebugUtil.ANIMATION_FACTOR) .withEndAction(new Runnable() { @Override public void run() { mLeftIconSwitcher.setVisibility(GONE); } }); mDetailsPanel.animate() .translationX(mLeftPadding + mIconSize + mLeftPadding) .setInterpolator(interpolator) .setDuration(duration * DebugUtil.ANIMATION_FACTOR); } } }