Java tutorial
/* * Copyright (c) 2014 Samuel Jarosiski <samueljarosinski@gmail.com> * * This file is part of "Tell me time". * http://tellmetime.info * * "Tell me time" is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * "Tell me time" is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with "Tell me time". If not, see <http://www.gnu.org/licenses/>. */ package info.tellmetime; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.app.WallpaperManager; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Typeface; import android.os.Build; import android.os.Handler; import android.service.dreams.DreamService; import android.support.v4.view.MotionEventCompat; import android.util.Property; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import java.io.File; import java.io.FileInputStream; import java.util.Calendar; @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public class DaydreamService extends DreamService { private Handler mHandler = new Handler(); private int mHighlightColor; private int mBacklightColor; private int mMinutesSize = 36; private int mShorterEdge; private float mDensity; private boolean isNightMode; @Override public void onAttachedToWindow() { super.onAttachedToWindow(); setInteractive(true); setFullscreen(true); setContentView(R.layout.daydream); LinearLayout mClock = (LinearLayout) findViewById(R.id.clock); SharedPreferences settings = getSharedPreferences("PREFS", Context.MODE_PRIVATE); mHighlightColor = settings.getInt(TellmetimeActivity.HIGHLIGHT, Color.WHITE); mBacklightColor = settings.getInt(TellmetimeActivity.BACKLIGHT, getResources().getColor(R.color.backlight_light)); mMinutesSize = settings.getInt(TellmetimeActivity.MINUTES_SIZE, 36); isNightMode = settings.getBoolean(TellmetimeActivity.NIGHTMODE, false); setScreenBright(!isNightMode); findViewById(R.id.overlay).setBackgroundColor( getResources().getColor(isNightMode ? R.color.night_mode_overlay : android.R.color.transparent)); RelativeLayout mSurface = (RelativeLayout) findViewById(R.id.surface); mSurface.setBackgroundColor( settings.getInt(TellmetimeActivity.BACKGROUND, getResources().getColor(R.color.background))); switch (settings.getInt(TellmetimeActivity.BACKGROUND_MODE, TellmetimeActivity.MODE_BACKGROUND_SOLID)) { case TellmetimeActivity.MODE_BACKGROUND_WALLPAPER: ((ImageView) findViewById(R.id.background_image)) .setImageDrawable(WallpaperManager.getInstance(this).getDrawable()); break; case TellmetimeActivity.MODE_BACKGROUND_IMAGE: try { ((ImageView) findViewById(R.id.background_image)).setImageBitmap(BitmapFactory.decodeStream( new FileInputStream(new File(getFilesDir(), TellmetimeActivity.IMAGE_FILE_NAME)))); } catch (Exception ignored) { // Image is not set, set background color loaded from setting is visible. } break; } mShorterEdge = Math.min(getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels); mDensity = getResources().getDisplayMetrics().density; RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); lp.addRule(RelativeLayout.CENTER_IN_PARENT); lp.width = mShorterEdge; mClock.setLayoutParams(lp); Typeface mTypeface = Typeface.createFromAsset(getAssets(), "Roboto-BoldCondensed.ttf"); final float mItemSize = mShorterEdge / mClock.getChildCount(); final int mRowMargin = (int) -(mItemSize / 2.2); for (int i = 0; i < mClock.getChildCount(); i++) { LinearLayout row = (LinearLayout) mClock.getChildAt(i); LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) row.getLayoutParams(); params.bottomMargin = mRowMargin; row.setLayoutParams(params); for (int j = 0; j < row.getChildCount(); j++) { TextView tv = (TextView) row.getChildAt(j); tv.setTypeface(mTypeface); tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mItemSize); tv.setTextColor(mBacklightColor); tv.setShadowLayer(mShorterEdge / 200 * mDensity, 0, 0, mBacklightColor); } } LinearLayout lastRow = (LinearLayout) mClock.getChildAt(mClock.getChildCount() - 1); LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) lastRow.getLayoutParams(); params.bottomMargin = 0; lastRow.setLayoutParams(params); TextView twenty = (TextView) findViewById(R.id.twenty); params = (LinearLayout.LayoutParams) twenty.getLayoutParams(); params.leftMargin = 0; twenty.setLayoutParams(params); inflateMinutesIndicators(); } @Override public void onDreamingStarted() { super.onDreamingStarted(); scheduleTimer(); } @Override public void onDreamingStopped() { super.onDreamingStopped(); mHandler.removeCallbacks(timerTask); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); inflateMinutesIndicators(); mClockAlgorithm.tickTock(); } private final Runnable timerTask = new Runnable() { @Override public void run() { scheduleTimer(); } }; private void scheduleTimer() { mClockAlgorithm.tickTock(); Calendar date = Calendar.getInstance(); date.set(Calendar.MILLISECOND, 0); date.set(Calendar.SECOND, 0); date.add(Calendar.MINUTE, 1); mHandler.postDelayed(timerTask, date.getTimeInMillis() - System.currentTimeMillis()); } Clock mClockAlgorithm = new Clock(true) { @Override protected void setColor(final String item, final boolean isHighlighting) { final int newColor = isHighlighting ? mHighlightColor : mBacklightColor; final TextView tv = (TextView) findViewById(getItem(item)); final int shadowSize = Math .min((isHighlighting ? mShorterEdge / 100 : mShorterEdge / 200) * (int) mDensity, 25); final Property<TextView, Integer> propertyHighlight = new Property<TextView, Integer>(int.class, "textColor") { @Override public Integer get(TextView object) { return object.getCurrentTextColor(); } @Override public void set(TextView object, Integer value) { object.setTextColor(value); object.setShadowLayer(shadowSize, 0, 0, value); } }; tv.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator animator = ObjectAnimator.ofInt(tv, propertyHighlight, newColor); animator.setDuration(1500L); animator.setEvaluator(new ArgbEvaluator()); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { tv.setLayerType(View.LAYER_TYPE_NONE, null); } }); animator.start(); } }; @Override public boolean dispatchTouchEvent(MotionEvent event) { if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { isNightMode = !isNightMode; findViewById(R.id.overlay).setBackgroundColor(getResources() .getColor(isNightMode ? R.color.night_mode_overlay : android.R.color.transparent)); setScreenBright(!isNightMode); return true; } else return super.dispatchTouchEvent(event); } private void inflateMinutesIndicators() { FrameLayout minutesLayout = (FrameLayout) findViewById(R.id.minutes_indicators); minutesLayout.removeAllViews(); LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); final boolean isLandscape = getResources() .getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; inflater.inflate(isLandscape ? R.layout.minutes_land : R.layout.minutes_portrait, minutesLayout); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, isLandscape ? FrameLayout.LayoutParams.MATCH_PARENT : FrameLayout.LayoutParams.WRAP_CONTENT); if (!isLandscape) { layoutParams.addRule(RelativeLayout.BELOW, R.id.clock); layoutParams.topMargin = (int) -TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mMinutesSize / 3, getResources().getDisplayMetrics()); } minutesLayout.setLayoutParams(layoutParams); Typeface mTypefaceBold = Typeface.createFromAsset(getAssets(), "Roboto-BoldCondensed.ttf"); ViewGroup minutesDots = (ViewGroup) findViewById(R.id.minutes_dots); for (int i = 0; i < minutesDots.getChildCount(); i++) { TextView m = (TextView) minutesDots.getChildAt(i); m.setTypeface(mTypefaceBold); m.setTextSize(TypedValue.COMPLEX_UNIT_DIP, mMinutesSize); m.setTextColor(mBacklightColor); m.setShadowLayer(mShorterEdge / 200 * mDensity, 0, 0, mBacklightColor); } } }