ClockFragment.java revision 1c7788b33dd4516dae81e6bcab043addc45fc1a1
1/* 2 * Copyright (C) 2012 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 17package com.android.deskclock; 18 19import android.app.PendingIntent; 20import android.content.BroadcastReceiver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.content.SharedPreferences; 25import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 26import android.content.res.Configuration; 27import android.os.Bundle; 28import android.os.Handler; 29import android.preference.PreferenceManager; 30import android.view.Gravity; 31import android.view.LayoutInflater; 32import android.view.MotionEvent; 33import android.view.View; 34import android.view.View.OnTouchListener; 35import android.view.ViewConfiguration; 36import android.view.ViewGroup; 37import android.view.animation.AnimationUtils; 38import android.widget.FrameLayout; 39import android.widget.ImageView; 40import android.widget.ListView; 41 42import com.android.deskclock.alarms.AlarmNotifications; 43import com.android.deskclock.worldclock.WorldClockAdapter; 44 45/** 46 * Fragment that shows the clock (analog or digital), the next alarm info and the world clock. 47 */ 48public class ClockFragment extends DeskClockFragment implements OnSharedPreferenceChangeListener { 49 50 private static final String BUTTONS_HIDDEN_KEY = "buttons_hidden"; 51 private final static String TAG = "ClockFragment"; 52 53 private boolean mButtonsHidden = false; 54 private View mDigitalClock, mAnalogClock, mClockFrame; 55 private WorldClockAdapter mAdapter; 56 private ListView mList; 57 private SharedPreferences mPrefs; 58 private String mDateFormat; 59 private String mDateFormatForAccessibility; 60 private String mDefaultClockStyle; 61 private String mClockStyle; 62 63 private PendingIntent mQuarterlyIntent; 64 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 65 @Override 66 public void onReceive(Context context, Intent intent) { 67 String action = intent.getAction(); 68 boolean changed = action.equals(Intent.ACTION_TIME_CHANGED) 69 || action.equals(Intent.ACTION_TIMEZONE_CHANGED) 70 || action.equals(Intent.ACTION_LOCALE_CHANGED); 71 if (changed || action.equals(Utils.ACTION_ON_QUARTER_HOUR)) { 72 Utils.updateDate(mDateFormat, mDateFormatForAccessibility,mClockFrame); 73 if (mAdapter != null) { 74 // *CHANGED may modify the need for showing the Home City 75 if (changed && (mAdapter.hasHomeCity() != mAdapter.needHomeCity())) { 76 mAdapter.reloadData(context); 77 } else { 78 mAdapter.notifyDataSetChanged(); 79 } 80 // Reloading the cities list with new localized names 81 if (action.equals(Intent.ACTION_LOCALE_CHANGED)) { 82 mAdapter.loadCitiesDb(context); 83 mAdapter.notifyDataSetChanged(); 84 } 85 } 86 } 87 if (changed || action.equals(AlarmNotifications.SYSTEM_ALARM_CHANGE_ACTION)) { 88 Utils.refreshAlarm(getActivity(), mClockFrame); 89 } 90 if (changed) { 91 mQuarterlyIntent = Utils.refreshAlarmOnQuarterHour(getActivity(), mQuarterlyIntent); 92 } 93 } 94 }; 95 96 private final Handler mHandler = new Handler(); 97 98 public ClockFragment() { 99 } 100 101 @Override 102 public View onCreateView(LayoutInflater inflater, ViewGroup container, 103 Bundle icicle) { 104 // Inflate the layout for this fragment 105 View v = inflater.inflate(R.layout.clock_fragment, container, false); 106 if (icicle != null) { 107 mButtonsHidden = icicle.getBoolean(BUTTONS_HIDDEN_KEY, false); 108 } 109 mList = (ListView)v.findViewById(R.id.cities); 110 mList.setDivider(null); 111 112 OnTouchListener longPressNightMode = new OnTouchListener() { 113 private float mMaxMovementAllowed = -1; 114 private int mLongPressTimeout = -1; 115 private float mLastTouchX, mLastTouchY; 116 117 @Override 118 public boolean onTouch(View v, MotionEvent event) { 119 if (mMaxMovementAllowed == -1) { 120 mMaxMovementAllowed = ViewConfiguration.get(getActivity()).getScaledTouchSlop(); 121 mLongPressTimeout = ViewConfiguration.getLongPressTimeout(); 122 } 123 124 switch (event.getAction()) { 125 case (MotionEvent.ACTION_DOWN): 126 long time = Utils.getTimeNow(); 127 mHandler.postDelayed(new Runnable() { 128 @Override 129 public void run() { 130 startActivity(new Intent(getActivity(), ScreensaverActivity.class)); 131 } 132 }, mLongPressTimeout); 133 mLastTouchX = event.getX(); 134 mLastTouchY = event.getY(); 135 return true; 136 case (MotionEvent.ACTION_MOVE): 137 float xDiff = Math.abs(event.getX()-mLastTouchX); 138 float yDiff = Math.abs(event.getY()-mLastTouchY); 139 if (xDiff >= mMaxMovementAllowed || yDiff >= mMaxMovementAllowed) { 140 mHandler.removeCallbacksAndMessages(null); 141 } 142 break; 143 default: 144 mHandler.removeCallbacksAndMessages(null); 145 } 146 return false; 147 } 148 }; 149 150 // On tablet landscape, the clock frame will be a distinct view. Otherwise, it'll be added 151 // on as a header to the main listview. 152 mClockFrame = v.findViewById(R.id.main_clock_left_pane); 153 if (mClockFrame == null) { 154 mClockFrame = inflater.inflate(R.layout.main_clock_frame, mList, false); 155 mList.addHeaderView(mClockFrame, null, false); 156 } else { 157 // The main clock frame needs its own touch listener for night mode now. 158 v.setOnTouchListener(longPressNightMode); 159 } 160 mList.setOnTouchListener(longPressNightMode); 161 162 mDigitalClock = mClockFrame.findViewById(R.id.digital_clock); 163 mAnalogClock = mClockFrame.findViewById(R.id.analog_clock); 164 View footerView = inflater.inflate(R.layout.blank_footer_view, mList, false); 165 footerView.setBackgroundResource(R.color.blackish); 166 mList.addFooterView(footerView); 167 mAdapter = new WorldClockAdapter(getActivity()); 168 mList.setAdapter(mAdapter); 169 170 // For landscape, put the cities button on the right and the menu in the actionbar. 171 View citiesButton = v.findViewById(R.id.cities_button); 172 View menuButton = v.findViewById(R.id.menu_button); 173 FrameLayout.LayoutParams layoutParams = 174 (FrameLayout.LayoutParams) citiesButton.getLayoutParams(); 175 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 176 layoutParams.gravity = Gravity.END; 177 menuButton.setVisibility(View.GONE); 178 } else { 179 layoutParams.gravity = Gravity.CENTER; 180 menuButton.setVisibility(View.VISIBLE); 181 } 182 citiesButton.setLayoutParams(layoutParams); 183 184 185 mPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); 186 mDefaultClockStyle = getActivity().getResources().getString(R.string.default_clock_style); 187 return v; 188 } 189 190 @Override 191 public void onResume () { 192 super.onResume(); 193 mPrefs.registerOnSharedPreferenceChangeListener(this); 194 mDateFormat = getString(R.string.abbrev_wday_month_day_no_year); 195 mDateFormatForAccessibility = getString(R.string.full_wday_month_day_no_year); 196 197 mQuarterlyIntent = Utils.startAlarmOnQuarterHour(getActivity()); 198 // Besides monitoring when quarter-hour changes, monitor other actions that 199 // effect clock time 200 IntentFilter filter = new IntentFilter(Utils.ACTION_ON_QUARTER_HOUR); 201 filter.addAction(AlarmNotifications.SYSTEM_ALARM_CHANGE_ACTION); 202 filter.addAction(Intent.ACTION_TIME_CHANGED); 203 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 204 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 205 getActivity().registerReceiver(mIntentReceiver, filter); 206 207 // Resume can invoked after changing the cities list or a change in locale 208 if (mAdapter != null) { 209 mAdapter.loadCitiesDb(getActivity()); 210 mAdapter.reloadData(getActivity()); 211 } 212 // Resume can invoked after changing the clock style. 213 View clockView = Utils.setClockStyle(getActivity(), mDigitalClock, mAnalogClock, 214 SettingsActivity.KEY_CLOCK_STYLE); 215 mClockStyle = (clockView == mDigitalClock ? 216 Utils.CLOCK_TYPE_DIGITAL : Utils.CLOCK_TYPE_ANALOG); 217 218 // Center the main clock frame if cities are empty. 219 if (getView().findViewById(R.id.main_clock_left_pane) != null && mAdapter.getCount() == 0) { 220 mList.setVisibility(View.GONE); 221 } else { 222 mList.setVisibility(View.VISIBLE); 223 } 224 mAdapter.notifyDataSetChanged(); 225 226 Utils.updateDate(mDateFormat, mDateFormatForAccessibility,mClockFrame); 227 Utils.refreshAlarm(getActivity(), mClockFrame); 228 } 229 230 @Override 231 public void onPause() { 232 super.onPause(); 233 mPrefs.unregisterOnSharedPreferenceChangeListener(this); 234 Utils.cancelAlarmOnQuarterHour(getActivity(), mQuarterlyIntent); 235 getActivity().unregisterReceiver(mIntentReceiver); 236 } 237 238 @Override 239 public void onSaveInstanceState (Bundle outState) { 240 outState.putBoolean(BUTTONS_HIDDEN_KEY, mButtonsHidden); 241 super.onSaveInstanceState(outState); 242 } 243 244 @Override 245 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 246 if (key == SettingsActivity.KEY_CLOCK_STYLE) { 247 mClockStyle = prefs.getString(SettingsActivity.KEY_CLOCK_STYLE, mDefaultClockStyle); 248 mAdapter.notifyDataSetChanged(); 249 } 250 } 251 } 252