Reorganize the your_train and departure_listing layouts (and corresponding custom views) for easier editing, greater flexibility for different screens, and to fix a layout bug that was introduced when updating the libraries where the "Your Train" section would be too wide.
General code cleanup, warnings fixes, and readability improvements.
This commit is contained in:
parent
4ee80b3f90
commit
2481f0c229
@ -17,6 +17,7 @@ import android.os.Handler;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.view.ActionMode;
|
import android.support.v7.view.ActionMode;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
@ -48,6 +49,7 @@ import com.dougkeen.bart.services.EtdService;
|
|||||||
import com.dougkeen.bart.services.EtdService.EtdServiceBinder;
|
import com.dougkeen.bart.services.EtdService.EtdServiceBinder;
|
||||||
import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
||||||
import com.dougkeen.bart.services.EtdService_;
|
import com.dougkeen.bart.services.EtdService_;
|
||||||
|
import com.dougkeen.util.Assert;
|
||||||
import com.dougkeen.util.Observer;
|
import com.dougkeen.util.Observer;
|
||||||
import com.dougkeen.util.WakeLocker;
|
import com.dougkeen.util.WakeLocker;
|
||||||
|
|
||||||
@ -86,8 +88,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
|||||||
|
|
||||||
mProgress = (ProgressBar) findViewById(android.R.id.progress);
|
mProgress = (ProgressBar) findViewById(android.R.id.progress);
|
||||||
|
|
||||||
mDeparturesAdapter = new DepartureArrayAdapter(this,
|
mDeparturesAdapter = new DepartureArrayAdapter(this);
|
||||||
R.layout.departure_listing);
|
|
||||||
|
|
||||||
setListAdapter(mDeparturesAdapter);
|
setListAdapter(mDeparturesAdapter);
|
||||||
final ListView listView = getListView();
|
final ListView listView = getListView();
|
||||||
@ -127,9 +128,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
if (savedInstanceState.containsKey("departures")) {
|
Parcelable[] departuresArray = savedInstanceState.getParcelableArray("departures");
|
||||||
for (Parcelable departure : savedInstanceState
|
if (departuresArray != null) {
|
||||||
.getParcelableArray("departures")) {
|
for (Parcelable departure : departuresArray) {
|
||||||
mDeparturesAdapter.add((Departure) departure);
|
mDeparturesAdapter.add((Departure) departure);
|
||||||
}
|
}
|
||||||
mDeparturesAdapter.notifyDataSetChanged();
|
mDeparturesAdapter.notifyDataSetChanged();
|
||||||
@ -151,8 +152,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
|||||||
}
|
}
|
||||||
refreshBoardedDeparture(false);
|
refreshBoardedDeparture(false);
|
||||||
|
|
||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
ActionBar supportActionBar = Assert.notNull(getSupportActionBar());
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
supportActionBar.setHomeButtonEnabled(true);
|
||||||
|
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
if (bartRunnerApplication.shouldPlayAlarmRingtone()) {
|
if (bartRunnerApplication.shouldPlayAlarmRingtone()) {
|
||||||
soundTheAlarm();
|
soundTheAlarm();
|
||||||
@ -440,7 +442,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mYourTrainSection.updateFromBoardedDeparture();
|
mYourTrainSection.updateFromBoardedDeparture(boardedDeparture);
|
||||||
|
|
||||||
if (currentVisibility != View.VISIBLE) {
|
if (currentVisibility != View.VISIBLE) {
|
||||||
showYourTrainSection(animate);
|
showYourTrainSection(animate);
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.dougkeen.bart.controls;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.widget.LinearLayoutCompat;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.Checkable;
|
||||||
|
|
||||||
|
import com.dougkeen.bart.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link android.widget.LinearLayout} that implements {@link Checkable} and changes
|
||||||
|
* its background color when checked.
|
||||||
|
*/
|
||||||
|
public class CheckableLinearLayout extends LinearLayoutCompat implements Checkable {
|
||||||
|
|
||||||
|
private boolean mChecked;
|
||||||
|
|
||||||
|
public CheckableLinearLayout(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckableLinearLayout(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChecked() {
|
||||||
|
return mChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChecked(boolean checked) {
|
||||||
|
mChecked = checked;
|
||||||
|
int colorRes = isChecked() ? R.color.blue_selection : android.R.color.transparent;
|
||||||
|
setBackgroundResource(colorRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toggle() {
|
||||||
|
setChecked(!isChecked());
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
package com.dougkeen.bart.controls;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.widget.Checkable;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
|
|
||||||
import com.dougkeen.bart.R;
|
|
||||||
|
|
||||||
public class DepartureListItemLayout extends RelativeLayout implements
|
|
||||||
Checkable {
|
|
||||||
|
|
||||||
public DepartureListItemLayout(Context context) {
|
|
||||||
super(context);
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.departure_listing, this,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean mChecked;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChecked() {
|
|
||||||
return mChecked;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setChecked(boolean checked) {
|
|
||||||
mChecked = checked;
|
|
||||||
if (isChecked()) {
|
|
||||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
|
||||||
R.color.blue_selection));
|
|
||||||
} else {
|
|
||||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
|
||||||
android.R.color.transparent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toggle() {
|
|
||||||
setChecked(!isChecked());
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,8 +10,7 @@ import android.widget.TextSwitcher;
|
|||||||
import com.dougkeen.bart.R;
|
import com.dougkeen.bart.R;
|
||||||
import com.dougkeen.bart.model.TextProvider;
|
import com.dougkeen.bart.model.TextProvider;
|
||||||
|
|
||||||
public class TimedTextSwitcher extends TextSwitcher implements
|
public class TimedTextSwitcher extends TextSwitcher implements Ticker.TickSubscriber {
|
||||||
Ticker.TickSubscriber {
|
|
||||||
|
|
||||||
public TimedTextSwitcher(Context context, AttributeSet attrs) {
|
public TimedTextSwitcher(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
@ -2,41 +2,51 @@ package com.dougkeen.bart.controls;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Checkable;
|
import android.widget.Checkable;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.dougkeen.bart.BartRunnerApplication;
|
|
||||||
import com.dougkeen.bart.R;
|
import com.dougkeen.bart.R;
|
||||||
import com.dougkeen.bart.model.Departure;
|
import com.dougkeen.bart.model.Departure;
|
||||||
import com.dougkeen.bart.model.TextProvider;
|
import com.dougkeen.bart.model.TextProvider;
|
||||||
import com.dougkeen.util.Observer;
|
import com.dougkeen.util.Observer;
|
||||||
|
|
||||||
public class YourTrainLayout extends RelativeLayout implements Checkable {
|
public class YourTrainLayout extends FrameLayout implements Checkable {
|
||||||
|
|
||||||
|
private final TextView destinationText;
|
||||||
|
private final TextView trainLength;
|
||||||
|
private final View colorBar;
|
||||||
|
private final ImageView bikeIcon;
|
||||||
|
private final View xferIcon;
|
||||||
|
private final CountdownTextView departureCountdown;
|
||||||
|
private final CountdownTextView arrivalCountdown;
|
||||||
|
private final TextView alarmText;
|
||||||
|
|
||||||
public YourTrainLayout(Context context) {
|
public YourTrainLayout(Context context) {
|
||||||
super(context);
|
this(context, null);
|
||||||
assignLayout(context);
|
}
|
||||||
|
|
||||||
|
public YourTrainLayout(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public YourTrainLayout(Context context, AttributeSet attrs, int defStyle) {
|
public YourTrainLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
assignLayout(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public YourTrainLayout(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
assignLayout(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assignLayout(Context context) {
|
|
||||||
LayoutInflater.from(context).inflate(R.layout.your_train, this, true);
|
LayoutInflater.from(context).inflate(R.layout.your_train, this, true);
|
||||||
|
|
||||||
|
destinationText = (TextView) findViewById(R.id.yourTrainDestinationText);
|
||||||
|
trainLength = (TextView) findViewById(R.id.yourTrainTrainLengthText);
|
||||||
|
colorBar = findViewById(R.id.yourTrainDestinationColorBar);
|
||||||
|
bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
||||||
|
xferIcon = findViewById(R.id.yourTrainXferIcon);
|
||||||
|
departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
||||||
|
arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
||||||
|
alarmText = (TextView) findViewById(R.id.alarmText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mChecked;
|
private boolean mChecked;
|
||||||
@ -75,13 +85,8 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setBackground() {
|
private void setBackground() {
|
||||||
if (isChecked()) {
|
int colorRes = isChecked() ? R.color.blue_selection : R.color.gray;
|
||||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
setBackgroundResource(colorRes);
|
||||||
R.color.blue_selection));
|
|
||||||
} else {
|
|
||||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
|
||||||
R.color.gray));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,11 +94,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
|||||||
setChecked(!isChecked());
|
setChecked(!isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateFromBoardedDeparture() {
|
public void updateFromBoardedDeparture(final Departure boardedDeparture) {
|
||||||
final Departure boardedDeparture = ((BartRunnerApplication) ((Activity) getContext())
|
if (boardedDeparture == null) {
|
||||||
.getApplication()).getBoardedDeparture();
|
|
||||||
if (boardedDeparture == null)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!boardedDeparture.equals(mDeparture)) {
|
if (!boardedDeparture.equals(mDeparture)) {
|
||||||
if (mDeparture != null) {
|
if (mDeparture != null) {
|
||||||
@ -110,36 +114,23 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
|||||||
|
|
||||||
mDeparture = boardedDeparture;
|
mDeparture = boardedDeparture;
|
||||||
|
|
||||||
((TextView) findViewById(R.id.yourTrainDestinationText))
|
destinationText.setText(boardedDeparture.getTrainDestination().toString());
|
||||||
.setText(boardedDeparture.getTrainDestination().toString());
|
trainLength.setText(boardedDeparture.getTrainLengthAndPlatform());
|
||||||
|
|
||||||
((TextView) findViewById(R.id.yourTrainTrainLengthText))
|
colorBar.setBackgroundColor(boardedDeparture.getTrainDestinationColor());
|
||||||
.setText(boardedDeparture.getTrainLengthAndPlatform());
|
|
||||||
|
|
||||||
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
|
|
||||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
|
||||||
.parseColor(boardedDeparture.getTrainDestinationColor()));
|
|
||||||
ImageView bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
|
||||||
if (boardedDeparture.isBikeAllowed()) {
|
if (boardedDeparture.isBikeAllowed()) {
|
||||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
bikeIcon.setImageResource(R.drawable.bike);
|
||||||
R.drawable.bike));
|
|
||||||
} else {
|
} else {
|
||||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
bikeIcon.setImageResource(R.drawable.nobike);
|
||||||
R.drawable.nobike));
|
|
||||||
}
|
}
|
||||||
if (boardedDeparture.getRequiresTransfer()) {
|
if (boardedDeparture.getRequiresTransfer()) {
|
||||||
findViewById(R.id.yourTrainXferIcon)
|
xferIcon.setVisibility(View.VISIBLE);
|
||||||
.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
} else {
|
||||||
findViewById(R.id.yourTrainXferIcon)
|
xferIcon.setVisibility(View.INVISIBLE);
|
||||||
.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAlarmIndicator();
|
updateAlarmIndicator();
|
||||||
|
|
||||||
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
|
||||||
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
|
||||||
|
|
||||||
final TextProvider textProvider = new TextProvider() {
|
final TextProvider textProvider = new TextProvider() {
|
||||||
@Override
|
@Override
|
||||||
public String getText(long tickNumber) {
|
public String getText(long tickNumber) {
|
||||||
@ -169,11 +160,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
|||||||
|
|
||||||
private void updateAlarmIndicator() {
|
private void updateAlarmIndicator() {
|
||||||
if (!mDeparture.isAlarmPending()) {
|
if (!mDeparture.isAlarmPending()) {
|
||||||
findViewById(R.id.alarmText).setVisibility(GONE);
|
alarmText.setVisibility(GONE);
|
||||||
} else {
|
} else {
|
||||||
findViewById(R.id.alarmText).setVisibility(VISIBLE);
|
alarmText.setVisibility(VISIBLE);
|
||||||
((TextView) findViewById(R.id.alarmText)).setText(String
|
alarmText.setText(String.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
||||||
.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package com.dougkeen.bart.data;
|
package com.dougkeen.bart.data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -21,65 +16,36 @@ import android.widget.ViewSwitcher.ViewFactory;
|
|||||||
|
|
||||||
import com.dougkeen.bart.R;
|
import com.dougkeen.bart.R;
|
||||||
import com.dougkeen.bart.controls.CountdownTextView;
|
import com.dougkeen.bart.controls.CountdownTextView;
|
||||||
import com.dougkeen.bart.controls.DepartureListItemLayout;
|
import com.dougkeen.bart.controls.CheckableLinearLayout;
|
||||||
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
||||||
import com.dougkeen.bart.model.Departure;
|
import com.dougkeen.bart.model.Departure;
|
||||||
import com.dougkeen.bart.model.TextProvider;
|
import com.dougkeen.bart.model.TextProvider;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||||
|
|
||||||
private Drawable noBikeDrawable;
|
private Drawable noBikeDrawable;
|
||||||
private Drawable bikeDrawable;
|
private Drawable bikeDrawable;
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
@SuppressWarnings("deprecation")
|
||||||
Departure[] objects) {
|
public DepartureArrayAdapter(Context context) {
|
||||||
super(context, textViewResourceId, objects);
|
super(context, 0 /* resource, unused since we override getView */);
|
||||||
assignBikeDrawables();
|
Resources resources = context.getResources();
|
||||||
}
|
// We need to use the deprecated getDrawable since the newer version that
|
||||||
|
// replaces it was only made available in API 21.
|
||||||
private void assignBikeDrawables() {
|
noBikeDrawable = resources.getDrawable(R.drawable.nobike);
|
||||||
noBikeDrawable = getContext().getResources().getDrawable(
|
bikeDrawable = resources.getDrawable(R.drawable.bike);
|
||||||
R.drawable.nobike);
|
|
||||||
bikeDrawable = getContext().getResources().getDrawable(R.drawable.bike);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int resource,
|
|
||||||
int textViewResourceId, Departure[] objects) {
|
|
||||||
super(context, resource, textViewResourceId, objects);
|
|
||||||
assignBikeDrawables();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int resource,
|
|
||||||
int textViewResourceId, List<Departure> objects) {
|
|
||||||
super(context, resource, textViewResourceId, objects);
|
|
||||||
assignBikeDrawables();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int resource,
|
|
||||||
int textViewResourceId) {
|
|
||||||
super(context, resource, textViewResourceId);
|
|
||||||
assignBikeDrawables();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
|
||||||
List<Departure> objects) {
|
|
||||||
super(context, textViewResourceId, objects);
|
|
||||||
assignBikeDrawables();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
|
||||||
super(context, textViewResourceId);
|
|
||||||
assignBikeDrawables();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
View view;
|
View view;
|
||||||
if (convertView != null
|
if (convertView != null && convertView instanceof CheckableLinearLayout) {
|
||||||
&& convertView instanceof DepartureListItemLayout) {
|
|
||||||
view = convertView;
|
view = convertView;
|
||||||
} else {
|
} else {
|
||||||
view = new DepartureListItemLayout(getContext());
|
view = LayoutInflater.from(getContext()).inflate(
|
||||||
|
R.layout.departure_listing, parent, false /* attachToRoot */);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Departure departure = getItem(position);
|
final Departure departure = getItem(position);
|
||||||
@ -132,10 +98,8 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageView colorBar = (ImageView) view
|
view.findViewById(R.id.destinationColorBar)
|
||||||
.findViewById(R.id.destinationColorBar);
|
.setBackgroundColor(departure.getTrainDestinationColor());
|
||||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
|
||||||
.parseColor(departure.getTrainDestinationColor()));
|
|
||||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||||
.findViewById(R.id.countdown);
|
.findViewById(R.id.countdown);
|
||||||
countdownTextView.setText(departure.getCountdownText());
|
countdownTextView.setText(departure.getCountdownText());
|
||||||
@ -179,11 +143,9 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
|||||||
bikeIcon.setImageDrawable(noBikeDrawable);
|
bikeIcon.setImageDrawable(noBikeDrawable);
|
||||||
}
|
}
|
||||||
if (departure.getRequiresTransfer()) {
|
if (departure.getRequiresTransfer()) {
|
||||||
view.findViewById(R.id.xferIcon)
|
view.findViewById(R.id.xferIcon).setVisibility(View.VISIBLE);
|
||||||
.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
} else {
|
||||||
view.findViewById(R.id.xferIcon)
|
view.findViewById(R.id.xferIcon).setVisibility(View.INVISIBLE);
|
||||||
.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
package com.dougkeen.bart.model;
|
package com.dougkeen.bart.model;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.NotificationCompat.Builder;
|
import android.support.v4.app.NotificationCompat.Builder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -23,6 +19,12 @@ import com.dougkeen.bart.activities.ViewDeparturesActivity;
|
|||||||
import com.dougkeen.bart.services.BoardedDepartureService;
|
import com.dougkeen.bart.services.BoardedDepartureService;
|
||||||
import com.dougkeen.util.Observable;
|
import com.dougkeen.util.Observable;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public class Departure implements Parcelable, Comparable<Departure> {
|
public class Departure implements Parcelable, Comparable<Departure> {
|
||||||
private static final int MINIMUM_MERGE_OVERLAP_MILLIS = 5000;
|
private static final int MINIMUM_MERGE_OVERLAP_MILLIS = 5000;
|
||||||
private static final int EXPIRE_MINUTES_AFTER_ARRIVAL = 1;
|
private static final int EXPIRE_MINUTES_AFTER_ARRIVAL = 1;
|
||||||
@ -133,8 +135,9 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
|||||||
this.line = line;
|
this.line = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTrainDestinationColor() {
|
@ColorInt
|
||||||
return destinationColor;
|
public int getTrainDestinationColor() {
|
||||||
|
return Color.parseColor(destinationColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTrainDestinationColor(String destinationColor) {
|
public void setTrainDestinationColor(String destinationColor) {
|
||||||
@ -627,33 +630,36 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
|||||||
final Intent cancelAlarmIntent = new Intent(context,
|
final Intent cancelAlarmIntent = new Intent(context,
|
||||||
BoardedDepartureService.class);
|
BoardedDepartureService.class);
|
||||||
cancelAlarmIntent.putExtra("cancelNotifications", true);
|
cancelAlarmIntent.putExtra("cancelNotifications", true);
|
||||||
|
String title = getOrigin().shortName + " to " + getPassengerDestination().shortName;
|
||||||
|
|
||||||
Builder notificationBuilder = new NotificationCompat.Builder(context)
|
Builder notificationBuilder = new NotificationCompat.Builder(context)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setSmallIcon(R.drawable.ic_stat_notification)
|
.setSmallIcon(R.drawable.ic_stat_notification)
|
||||||
.setContentTitle(
|
.setContentTitle(title)
|
||||||
getOrigin().shortName + " to "
|
|
||||||
+ getPassengerDestination().shortName)
|
|
||||||
.setContentIntent(getNotificationIntent(context)).setWhen(0);
|
.setContentIntent(getNotificationIntent(context)).setWhen(0);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 16) {
|
if (android.os.Build.VERSION.SDK_INT >= 16) {
|
||||||
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
|
notificationBuilder
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
.setContentText(minutesText + " until departure");
|
.setContentText(minutesText + " until departure");
|
||||||
|
|
||||||
if (isAlarmPending()) {
|
if (isAlarmPending()) {
|
||||||
notificationBuilder.addAction(
|
PendingIntent pendingIntent = PendingIntent.getService(
|
||||||
R.drawable.ic_action_cancel_alarm,
|
context, 0, cancelAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
"Cancel alarm",
|
String subText = "Alarm " + getAlarmLeadTimeMinutes() + " minutes before departure";
|
||||||
PendingIntent.getService(context, 0, cancelAlarmIntent,
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT)).setSubText(
|
notificationBuilder
|
||||||
"Alarm " + getAlarmLeadTimeMinutes()
|
.addAction(R.drawable.ic_action_cancel_alarm, "Cancel alarm", pendingIntent)
|
||||||
+ " minutes before departure");
|
.setSubText(subText);
|
||||||
}
|
}
|
||||||
} else if (isAlarmPending()) {
|
} else if (isAlarmPending()) {
|
||||||
notificationBuilder.setContentText(minutesText
|
String text = minutesText
|
||||||
+ " to departure (alarm at " + getAlarmLeadTimeMinutes()
|
+ " to departure (alarm at " + getAlarmLeadTimeMinutes()
|
||||||
+ " min" + ((getAlarmLeadTimeMinutes() == 1) ? "" : "s")
|
+ " min" + ((getAlarmLeadTimeMinutes() == 1) ? "" : "s")
|
||||||
+ ")");
|
+ ")";
|
||||||
|
notificationBuilder.setContentText(text);
|
||||||
} else {
|
} else {
|
||||||
notificationBuilder
|
notificationBuilder.setContentText(minutesText + " until departure");
|
||||||
.setContentText(minutesText + " until departure");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return notificationBuilder.build();
|
return notificationBuilder.build();
|
||||||
|
@ -4,7 +4,6 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -15,6 +14,7 @@ import android.os.HandlerThread;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.support.v4.app.NotificationManagerCompat;
|
||||||
|
|
||||||
import com.dougkeen.bart.BartRunnerApplication;
|
import com.dougkeen.bart.BartRunnerApplication;
|
||||||
import com.dougkeen.bart.model.Departure;
|
import com.dougkeen.bart.model.Departure;
|
||||||
@ -34,7 +34,7 @@ public class BoardedDepartureService extends Service implements
|
|||||||
private boolean mBound = false;
|
private boolean mBound = false;
|
||||||
private EtdService mEtdService;
|
private EtdService mEtdService;
|
||||||
private StationPair mStationPair;
|
private StationPair mStationPair;
|
||||||
private NotificationManager mNotificationManager;
|
private NotificationManagerCompat mNotificationManager;
|
||||||
private AlarmManager mAlarmManager;
|
private AlarmManager mAlarmManager;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private boolean mHasShutDown = false;
|
private boolean mHasShutDown = false;
|
||||||
@ -91,7 +91,7 @@ public class BoardedDepartureService extends Service implements
|
|||||||
|
|
||||||
bindService(EtdService_.intent(this).get(), mConnection,
|
bindService(EtdService_.intent(this).get(), mConnection,
|
||||||
Context.BIND_AUTO_CREATE);
|
Context.BIND_AUTO_CREATE);
|
||||||
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
mNotificationManager = NotificationManagerCompat.from(this);
|
||||||
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||||
mHandler = new Handler();
|
mHandler = new Handler();
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
@ -302,8 +302,7 @@ public class BoardedDepartureService extends Service implements
|
|||||||
.getBoardedDeparture();
|
.getBoardedDeparture();
|
||||||
if (boardedDeparture != null) {
|
if (boardedDeparture != null) {
|
||||||
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
|
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
|
||||||
boardedDeparture
|
boardedDeparture.createNotification(getApplicationContext()));
|
||||||
.createNotification(getApplicationContext()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
app/src/main/java/com/dougkeen/util/Assert.java
Normal file
13
app/src/main/java/com/dougkeen/util/Assert.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.dougkeen.util;
|
||||||
|
|
||||||
|
public final class Assert {
|
||||||
|
// Uninstantiable
|
||||||
|
private Assert() {}
|
||||||
|
|
||||||
|
public static <T> T notNull(T obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
throw new AssertionError("Expected object to be non-null");
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
@ -1,77 +1,111 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merge
|
<com.dougkeen.bart.controls.CheckableLinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="fill_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
|
||||||
<ImageView
|
<!-- This layout is used when the height is >= 480 dp, eg usually in portrait mode. -->
|
||||||
|
|
||||||
|
<View
|
||||||
android:id="@+id/destinationColorBar"
|
android:id="@+id/destinationColorBar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="15dp"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:layout_alignParentLeft="true"
|
tools:background="#F00"
|
||||||
android:layout_centerVertical="true"
|
/>
|
||||||
android:src="@drawable/basic_rectangle" />
|
|
||||||
|
|
||||||
|
<!-- Holds the destination, the train info, and the arrival time -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/topRow"
|
android:layout_width="0dp"
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_marginLeft="5dp"
|
||||||
android:layout_toRightOf="@id/destinationColorBar">
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/destinationText"
|
android:id="@+id/destinationText"
|
||||||
style="@style/DepartureDestinationText"
|
style="@style/DepartureDestinationText"
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:singleLine="true" />
|
android:singleLine="true"
|
||||||
|
tools:text="Richmond"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/trainLengthText"
|
||||||
|
style="@style/DepartureUncertaintyText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="9 cars, platform 2"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/estimatedArrival"
|
||||||
|
style="@style/DepartureUncertaintyText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="Arrives ~11:12 AM (20 mins)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Holds the bike and xfer icons -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/bikeIcon"
|
android:id="@+id/bikeIcon"
|
||||||
style="@style/BikeIcon" />
|
style="@style/TrainInfoIcon"
|
||||||
|
tools:src="@drawable/bike"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/xferIcon"
|
||||||
|
style="@style/TrainInfoIcon"
|
||||||
|
android:src="@drawable/xfer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Holds the departure countdown, uncertainty, and departure time -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:gravity="right"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.CountdownTextView
|
<com.dougkeen.bart.controls.CountdownTextView
|
||||||
android:id="@+id/countdown"
|
android:id="@+id/countdown"
|
||||||
style="@style/DepartureCountdownText"
|
style="@style/DepartureCountdownText"
|
||||||
android:gravity="right"
|
|
||||||
android:width="90dp"
|
android:width="90dp"
|
||||||
bart:tickInterval="1" />
|
android:gravity="right"
|
||||||
|
bart:tickInterval="1"
|
||||||
|
tools:text="9m, 57s"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uncertainty"
|
||||||
|
style="@style/DepartureUncertaintyText"
|
||||||
|
tools:text="(+8s)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/departureTime"
|
||||||
|
style="@style/DepartureUncertaintyText"
|
||||||
|
tools:text="11:20 AM"
|
||||||
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<ImageView
|
</com.dougkeen.bart.controls.CheckableLinearLayout>
|
||||||
android:id="@+id/xferIcon"
|
|
||||||
style="@style/XferIcon"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/topRow"
|
|
||||||
android:src="@drawable/xfer" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/trainLengthText"
|
|
||||||
style="@style/DepartureUncertaintyText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/topRow"
|
|
||||||
android:layout_toRightOf="@id/destinationColorBar" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/uncertainty"
|
|
||||||
style="@style/DepartureUncertaintyText"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/topRow" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/estimatedArrival"
|
|
||||||
style="@style/DepartureUncertaintyText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/trainLengthText"
|
|
||||||
android:layout_toRightOf="@id/destinationColorBar" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/departureTime"
|
|
||||||
style="@style/DepartureUncertaintyText"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/uncertainty" />
|
|
||||||
|
|
||||||
</merge>
|
|
||||||
|
@ -1,64 +1,98 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merge
|
<com.dougkeen.bart.controls.CheckableLinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent">
|
android:layout_height="fill_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
>
|
||||||
|
|
||||||
<ImageView
|
<!-- This layout is used when the height is less than 480 dp (eg usually in landscape mode) -->
|
||||||
|
|
||||||
|
<View
|
||||||
android:id="@+id/destinationColorBar"
|
android:id="@+id/destinationColorBar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="15dp"
|
||||||
android:layout_height="45dp"
|
android:layout_height="45dp"
|
||||||
android:layout_alignParentLeft="true"
|
tools:background="#F00"
|
||||||
android:layout_centerVertical="true"
|
/>
|
||||||
android:src="@drawable/basic_rectangle" />
|
|
||||||
|
|
||||||
|
<!-- Holds destination and train info/arrival -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/topRow"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_marginLeft="5dp"
|
||||||
android:layout_toRightOf="@id/destinationColorBar">
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/destinationText"
|
android:id="@+id/destinationText"
|
||||||
style="@style/DepartureDestinationText"
|
style="@style/DepartureDestinationText"
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:singleLine="true" />
|
android:singleLine="true"
|
||||||
|
tools:text="Richmond"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||||
|
android:id="@+id/trainLengthText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
bart:tickInterval="1"
|
||||||
|
tools:text="9 cars, platform 2"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Holds bike and xfer icons -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/bikeIcon"
|
android:id="@+id/bikeIcon"
|
||||||
style="@style/BikeIcon" />
|
style="@style/TrainInfoIcon"
|
||||||
|
tools:src="@drawable/bike"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/xferIcon"
|
||||||
|
style="@style/TrainInfoIcon"
|
||||||
|
android:src="@drawable/xfer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Holds departure countdown and uncertainty/departure time-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:gravity="right"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.CountdownTextView
|
<com.dougkeen.bart.controls.CountdownTextView
|
||||||
android:id="@+id/countdown"
|
android:id="@+id/countdown"
|
||||||
style="@style/DepartureCountdownText"
|
style="@style/DepartureCountdownText"
|
||||||
android:gravity="right"
|
|
||||||
android:width="90dp"
|
android:width="90dp"
|
||||||
bart:tickInterval="1" />
|
android:gravity="right"
|
||||||
|
bart:tickInterval="1"
|
||||||
|
tools:text="9m, 57s"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||||
|
android:id="@+id/uncertainty"
|
||||||
|
style="@style/DepartureUncertaintyText"
|
||||||
|
bart:tickInterval="1"
|
||||||
|
tools:text="(+8s)"
|
||||||
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<ImageView
|
</com.dougkeen.bart.controls.CheckableLinearLayout>
|
||||||
android:id="@+id/xferIcon"
|
|
||||||
style="@style/XferIcon"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/topRow"
|
|
||||||
android:src="@drawable/xfer" />
|
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
|
||||||
android:id="@+id/trainLengthText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/topRow"
|
|
||||||
android:layout_toRightOf="@id/destinationColorBar"
|
|
||||||
bart:tickInterval="1" />
|
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
|
||||||
android:id="@+id/uncertainty"
|
|
||||||
style="@style/DepartureUncertaintyText"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/topRow"
|
|
||||||
bart:tickInterval="1" />
|
|
||||||
|
|
||||||
</merge>
|
|
||||||
|
@ -1,82 +1,121 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merge
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:bart="http://schemas.android.com/apk/res-auto" >
|
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
<TextView
|
<!-- Holds the "Your Train" title and the alarm indicator -->
|
||||||
android:id="@+id/alarmText"
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/yourTrainHeader"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/your_train"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textSize="20dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/alarmText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:drawableLeft="@drawable/ic_action_alarm"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textSize="16dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="5"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- Holds the color bar, destination text, train info, bike icon, and xfer icon -->
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentRight="true"
|
android:orientation="horizontal"
|
||||||
android:layout_alignParentTop="true"
|
>
|
||||||
android:drawableLeft="@drawable/ic_action_alarm"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:textSize="16dp"
|
|
||||||
android:visibility="gone"></TextView>
|
|
||||||
|
|
||||||
<TextView
|
<View
|
||||||
android:id="@+id/yourTrainHeader"
|
android:id="@+id/yourTrainDestinationColorBar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="15dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="45dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_centerHorizontal="true"
|
tools:background="#F00"
|
||||||
android:text="@string/your_train"
|
/>
|
||||||
android:textAllCaps="true"
|
|
||||||
android:textSize="20dp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
<ImageView
|
<!-- Holds the destination text and train info -->
|
||||||
android:id="@+id/yourTrainDestinationColorBar"
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="45dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_below="@id/yourTrainHeader"
|
android:orientation="vertical"
|
||||||
android:src="@drawable/basic_rectangle" />
|
android:padding="5dp"
|
||||||
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/yourTrainDestinationText"
|
android:id="@+id/yourTrainDestinationText"
|
||||||
style="@style/DepartureDestinationText"
|
style="@style/DepartureDestinationText"
|
||||||
android:layout_below="@id/yourTrainHeader"
|
android:ellipsize="marquee"
|
||||||
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
|
android:singleLine="true"
|
||||||
android:ellipsize="marquee"
|
tools:text="Richmond"
|
||||||
android:singleLine="true" />
|
/>
|
||||||
|
|
||||||
<ImageView
|
<TextView
|
||||||
android:id="@+id/yourTrainBikeIcon"
|
android:id="@+id/yourTrainTrainLengthText"
|
||||||
style="@style/BikeIcon"
|
android:layout_width="wrap_content"
|
||||||
android:layout_below="@id/yourTrainHeader"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toRightOf="@id/yourTrainDestinationText" />
|
tools:text="9 cars, platform 2"
|
||||||
|
/>
|
||||||
|
|
||||||
<ImageView
|
</LinearLayout>
|
||||||
android:id="@+id/yourTrainXferIcon"
|
|
||||||
style="@style/XferIcon"
|
|
||||||
android:layout_below="@id/yourTrainBikeIcon"
|
|
||||||
android:layout_toRightOf="@id/yourTrainDestinationText"
|
|
||||||
android:src="@drawable/xfer" />
|
|
||||||
|
|
||||||
<TextView
|
<!-- Holds the bike icon and xfer icon -->
|
||||||
android:id="@+id/yourTrainTrainLengthText"
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/yourTrainDestinationText"
|
android:orientation="vertical"
|
||||||
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
|
>
|
||||||
android:paddingLeft="5dp" />
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/yourTrainBikeIcon"
|
||||||
|
style="@style/TrainInfoIcon"
|
||||||
|
tools:src="@drawable/bike"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/yourTrainXferIcon"
|
||||||
|
style="@style/TrainInfoIcon"
|
||||||
|
android:src="@drawable/xfer"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.CountdownTextView
|
<com.dougkeen.bart.controls.CountdownTextView
|
||||||
android:id="@+id/yourTrainDepartureCountdown"
|
android:id="@+id/yourTrainDepartureCountdown"
|
||||||
style="@style/DepartureCountdownText"
|
style="@style/DepartureCountdownText"
|
||||||
android:layout_alignLeft="@id/yourTrainSection"
|
bart:tickInterval="1"
|
||||||
android:layout_alignRight="@id/yourTrainSection"
|
tools:text="Leaves in 15 min, 20s (+8s)"
|
||||||
android:layout_below="@id/yourTrainTrainLengthText"
|
/>
|
||||||
bart:tickInterval="1" />
|
|
||||||
|
|
||||||
<com.dougkeen.bart.controls.CountdownTextView
|
<com.dougkeen.bart.controls.CountdownTextView
|
||||||
android:id="@+id/yourTrainArrivalCountdown"
|
android:id="@+id/yourTrainArrivalCountdown"
|
||||||
style="@style/DepartureCountdownText"
|
style="@style/DepartureCountdownText"
|
||||||
android:layout_alignLeft="@id/yourTrainSection"
|
|
||||||
android:layout_alignRight="@id/yourTrainSection"
|
|
||||||
android:layout_below="@id/yourTrainDepartureCountdown"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
bart:tickInterval="5" />
|
bart:tickInterval="5"
|
||||||
|
tools:text="Arrives ~11:12 AM (20 mins)"
|
||||||
|
/>
|
||||||
|
|
||||||
</merge>
|
</LinearLayout>
|
||||||
|
@ -92,18 +92,10 @@
|
|||||||
<item name="android:gravity">center</item>
|
<item name="android:gravity">center</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="BikeIcon">
|
<style name="TrainInfoIcon">
|
||||||
<item name="android:layout_width">wrap_content</item>
|
<item name="android:layout_width">wrap_content</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:layout_marginTop">5dp</item>
|
<item name="android:layout_margin">5dp</item>
|
||||||
<item name="android:layout_marginLeft">5dp</item>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="XferIcon">
|
|
||||||
<item name="android:layout_width">wrap_content</item>
|
|
||||||
<item name="android:layout_height">wrap_content</item>
|
|
||||||
<item name="android:layout_marginRight">87dp</item>
|
|
||||||
<item name="android:layout_marginBottom">5dp</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user