Merge pull request #6 from FuegoFro/clean_up_your_train_view

Reorganize train info views and general code cleanup
This commit is contained in:
Doug Keen 2015-10-18 15:52:31 -07:00
commit 4b8b7af55a
13 changed files with 424 additions and 350 deletions

View File

@ -17,6 +17,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Parcelable;
import android.os.Vibrator;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
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.EtdServiceListener;
import com.dougkeen.bart.services.EtdService_;
import com.dougkeen.util.Assert;
import com.dougkeen.util.Observer;
import com.dougkeen.util.WakeLocker;
@ -86,8 +88,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
mProgress = (ProgressBar) findViewById(android.R.id.progress);
mDeparturesAdapter = new DepartureArrayAdapter(this,
R.layout.departure_listing);
mDeparturesAdapter = new DepartureArrayAdapter(this);
setListAdapter(mDeparturesAdapter);
final ListView listView = getListView();
@ -127,9 +128,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
}
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("departures")) {
for (Parcelable departure : savedInstanceState
.getParcelableArray("departures")) {
Parcelable[] departuresArray = savedInstanceState.getParcelableArray("departures");
if (departuresArray != null) {
for (Parcelable departure : departuresArray) {
mDeparturesAdapter.add((Departure) departure);
}
mDeparturesAdapter.notifyDataSetChanged();
@ -151,8 +152,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
}
refreshBoardedDeparture(false);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar supportActionBar = Assert.notNull(getSupportActionBar());
supportActionBar.setHomeButtonEnabled(true);
supportActionBar.setDisplayHomeAsUpEnabled(true);
if (bartRunnerApplication.shouldPlayAlarmRingtone()) {
soundTheAlarm();
@ -440,7 +442,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
return;
}
mYourTrainSection.updateFromBoardedDeparture();
mYourTrainSection.updateFromBoardedDeparture(boardedDeparture);
if (currentVisibility != View.VISIBLE) {
showYourTrainSection(animate);

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -10,8 +10,7 @@ import android.widget.TextSwitcher;
import com.dougkeen.bart.R;
import com.dougkeen.bart.model.TextProvider;
public class TimedTextSwitcher extends TextSwitcher implements
Ticker.TickSubscriber {
public class TimedTextSwitcher extends TextSwitcher implements Ticker.TickSubscriber {
public TimedTextSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);

View File

@ -2,41 +2,51 @@ package com.dougkeen.bart.controls;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.dougkeen.bart.BartRunnerApplication;
import com.dougkeen.bart.R;
import com.dougkeen.bart.model.Departure;
import com.dougkeen.bart.model.TextProvider;
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) {
super(context);
assignLayout(context);
this(context, null);
}
public YourTrainLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public YourTrainLayout(Context context, AttributeSet attrs, int 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);
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;
@ -75,13 +85,8 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
}
private void setBackground() {
if (isChecked()) {
setBackgroundDrawable(getContext().getResources().getDrawable(
R.color.blue_selection));
} else {
setBackgroundDrawable(getContext().getResources().getDrawable(
R.color.gray));
}
int colorRes = isChecked() ? R.color.blue_selection : R.color.gray;
setBackgroundResource(colorRes);
}
@Override
@ -89,11 +94,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
setChecked(!isChecked());
}
public void updateFromBoardedDeparture() {
final Departure boardedDeparture = ((BartRunnerApplication) ((Activity) getContext())
.getApplication()).getBoardedDeparture();
if (boardedDeparture == null)
public void updateFromBoardedDeparture(final Departure boardedDeparture) {
if (boardedDeparture == null) {
return;
}
if (!boardedDeparture.equals(mDeparture)) {
if (mDeparture != null) {
@ -110,36 +114,23 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
mDeparture = boardedDeparture;
((TextView) findViewById(R.id.yourTrainDestinationText))
.setText(boardedDeparture.getTrainDestination().toString());
destinationText.setText(boardedDeparture.getTrainDestination().toString());
trainLength.setText(boardedDeparture.getTrainLengthAndPlatform());
((TextView) findViewById(R.id.yourTrainTrainLengthText))
.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);
colorBar.setBackgroundColor(boardedDeparture.getTrainDestinationColor());
if (boardedDeparture.isBikeAllowed()) {
bikeIcon.setImageDrawable(getResources().getDrawable(
R.drawable.bike));
bikeIcon.setImageResource(R.drawable.bike);
} else {
bikeIcon.setImageDrawable(getResources().getDrawable(
R.drawable.nobike));
bikeIcon.setImageResource(R.drawable.nobike);
}
if (boardedDeparture.getRequiresTransfer()) {
findViewById(R.id.yourTrainXferIcon)
.setVisibility(View.VISIBLE);
xferIcon.setVisibility(View.VISIBLE);
} else {
findViewById(R.id.yourTrainXferIcon)
.setVisibility(View.INVISIBLE);
xferIcon.setVisibility(View.INVISIBLE);
}
updateAlarmIndicator();
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
final TextProvider textProvider = new TextProvider() {
@Override
public String getText(long tickNumber) {
@ -169,11 +160,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
private void updateAlarmIndicator() {
if (!mDeparture.isAlarmPending()) {
findViewById(R.id.alarmText).setVisibility(GONE);
alarmText.setVisibility(GONE);
} else {
findViewById(R.id.alarmText).setVisibility(VISIBLE);
((TextView) findViewById(R.id.alarmText)).setText(String
.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
alarmText.setVisibility(VISIBLE);
alarmText.setText(String.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
}
}

View File

@ -1,13 +1,8 @@
package com.dougkeen.bart.data;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.graphics.Color;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -21,65 +16,36 @@ import android.widget.ViewSwitcher.ViewFactory;
import com.dougkeen.bart.R;
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.model.Departure;
import com.dougkeen.bart.model.TextProvider;
import org.apache.commons.lang3.StringUtils;
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
private Drawable noBikeDrawable;
private Drawable bikeDrawable;
public DepartureArrayAdapter(Context context, int textViewResourceId,
Departure[] objects) {
super(context, textViewResourceId, objects);
assignBikeDrawables();
}
private void assignBikeDrawables() {
noBikeDrawable = getContext().getResources().getDrawable(
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();
@SuppressWarnings("deprecation")
public DepartureArrayAdapter(Context context) {
super(context, 0 /* resource, unused since we override getView */);
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.
noBikeDrawable = resources.getDrawable(R.drawable.nobike);
bikeDrawable = resources.getDrawable(R.drawable.bike);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView != null
&& convertView instanceof DepartureListItemLayout) {
if (convertView != null && convertView instanceof CheckableLinearLayout) {
view = convertView;
} else {
view = new DepartureListItemLayout(getContext());
view = LayoutInflater.from(getContext()).inflate(
R.layout.departure_listing, parent, false /* attachToRoot */);
}
final Departure departure = getItem(position);
@ -132,10 +98,8 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
});
}
ImageView colorBar = (ImageView) view
.findViewById(R.id.destinationColorBar);
((GradientDrawable) colorBar.getDrawable()).setColor(Color
.parseColor(departure.getTrainDestinationColor()));
view.findViewById(R.id.destinationColorBar)
.setBackgroundColor(departure.getTrainDestinationColor());
CountdownTextView countdownTextView = (CountdownTextView) view
.findViewById(R.id.countdown);
countdownTextView.setText(departure.getCountdownText());
@ -171,7 +135,7 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
}
});
}
ImageView bikeIcon = (ImageView) view.findViewById(R.id.bikeIcon);
if (departure.isBikeAllowed()) {
bikeIcon.setImageDrawable(bikeDrawable);
@ -179,11 +143,9 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
bikeIcon.setImageDrawable(noBikeDrawable);
}
if (departure.getRequiresTransfer()) {
view.findViewById(R.id.xferIcon)
.setVisibility(View.VISIBLE);
view.findViewById(R.id.xferIcon).setVisibility(View.VISIBLE);
} else {
view.findViewById(R.id.xferIcon)
.setVisibility(View.INVISIBLE);
view.findViewById(R.id.xferIcon).setVisibility(View.INVISIBLE);
}
return view;

View File

@ -1,18 +1,14 @@
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.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.ColorInt;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;
@ -23,6 +19,12 @@ import com.dougkeen.bart.activities.ViewDeparturesActivity;
import com.dougkeen.bart.services.BoardedDepartureService;
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> {
private static final int MINIMUM_MERGE_OVERLAP_MILLIS = 5000;
private static final int EXPIRE_MINUTES_AFTER_ARRIVAL = 1;
@ -133,8 +135,9 @@ public class Departure implements Parcelable, Comparable<Departure> {
this.line = line;
}
public String getTrainDestinationColor() {
return destinationColor;
@ColorInt
public int getTrainDestinationColor() {
return Color.parseColor(destinationColor);
}
public void setTrainDestinationColor(String destinationColor) {
@ -627,33 +630,36 @@ public class Departure implements Parcelable, Comparable<Departure> {
final Intent cancelAlarmIntent = new Intent(context,
BoardedDepartureService.class);
cancelAlarmIntent.putExtra("cancelNotifications", true);
String title = getOrigin().shortName + " to " + getPassengerDestination().shortName;
Builder notificationBuilder = new NotificationCompat.Builder(context)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(
getOrigin().shortName + " to "
+ getPassengerDestination().shortName)
.setContentTitle(title)
.setContentIntent(getNotificationIntent(context)).setWhen(0);
if (android.os.Build.VERSION.SDK_INT >= 16) {
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationBuilder
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentText(minutesText + " until departure");
if (isAlarmPending()) {
notificationBuilder.addAction(
R.drawable.ic_action_cancel_alarm,
"Cancel alarm",
PendingIntent.getService(context, 0, cancelAlarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT)).setSubText(
"Alarm " + getAlarmLeadTimeMinutes()
+ " minutes before departure");
PendingIntent pendingIntent = PendingIntent.getService(
context, 0, cancelAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
String subText = "Alarm " + getAlarmLeadTimeMinutes() + " minutes before departure";
notificationBuilder
.addAction(R.drawable.ic_action_cancel_alarm, "Cancel alarm", pendingIntent)
.setSubText(subText);
}
} else if (isAlarmPending()) {
notificationBuilder.setContentText(minutesText
String text = minutesText
+ " to departure (alarm at " + getAlarmLeadTimeMinutes()
+ " min" + ((getAlarmLeadTimeMinutes() == 1) ? "" : "s")
+ ")");
+ ")";
notificationBuilder.setContentText(text);
} else {
notificationBuilder
.setContentText(minutesText + " until departure");
notificationBuilder.setContentText(minutesText + " until departure");
}
return notificationBuilder.build();

View File

@ -4,7 +4,6 @@ import java.lang.ref.WeakReference;
import java.util.List;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@ -15,6 +14,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.NotificationManagerCompat;
import com.dougkeen.bart.BartRunnerApplication;
import com.dougkeen.bart.model.Departure;
@ -34,7 +34,7 @@ public class BoardedDepartureService extends Service implements
private boolean mBound = false;
private EtdService mEtdService;
private StationPair mStationPair;
private NotificationManager mNotificationManager;
private NotificationManagerCompat mNotificationManager;
private AlarmManager mAlarmManager;
private Handler mHandler;
private boolean mHasShutDown = false;
@ -91,7 +91,7 @@ public class BoardedDepartureService extends Service implements
bindService(EtdService_.intent(this).get(), mConnection,
Context.BIND_AUTO_CREATE);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager = NotificationManagerCompat.from(this);
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
mHandler = new Handler();
super.onCreate();
@ -302,8 +302,7 @@ public class BoardedDepartureService extends Service implements
.getBoardedDeparture();
if (boardedDeparture != null) {
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
boardedDeparture
.createNotification(getApplicationContext()));
boardedDeparture.createNotification(getApplicationContext()));
}
}

View 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;
}
}

View File

@ -1,77 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
<com.dougkeen.bart.controls.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bart="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
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:layout_width="wrap_content"
android:layout_width="15dp"
android:layout_height="64dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/basic_rectangle" />
tools:background="#F00"
/>
<!-- Holds the destination, the train info, and the arrival time -->
<LinearLayout
android:id="@+id/topRow"
android:layout_width="fill_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/destinationColorBar">
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:orientation="vertical"
>
<TextView
android:id="@+id/destinationText"
style="@style/DepartureDestinationText"
android:layout_weight="1"
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
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
android:id="@+id/countdown"
style="@style/DepartureCountdownText"
android:gravity="right"
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>
<ImageView
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>
</com.dougkeen.bart.controls.CheckableLinearLayout>

View File

@ -1,64 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
<com.dougkeen.bart.controls.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bart="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
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:layout_width="wrap_content"
android:layout_width="15dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/basic_rectangle" />
tools:background="#F00"
/>
<!-- Holds destination and train info/arrival -->
<LinearLayout
android:id="@+id/topRow"
android:layout_width="fill_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/destinationColorBar">
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:orientation="vertical"
>
<TextView
android:id="@+id/destinationText"
style="@style/DepartureDestinationText"
android:layout_weight="1"
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
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
android:id="@+id/countdown"
style="@style/DepartureCountdownText"
android:gravity="right"
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>
<ImageView
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>
</com.dougkeen.bart.controls.CheckableLinearLayout>

View File

@ -1,82 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<merge
<LinearLayout
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
android:id="@+id/alarmText"
<!-- Holds the "Your Train" title and the alarm indicator -->
<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_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:drawableLeft="@drawable/ic_action_alarm"
android:gravity="center_vertical"
android:textSize="16dp"
android:visibility="gone"></TextView>
android:orientation="horizontal"
>
<TextView
android:id="@+id/yourTrainHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="@string/your_train"
android:textAllCaps="true"
android:textSize="20dp"
android:textStyle="bold" />
<View
android:id="@+id/yourTrainDestinationColorBar"
android:layout_width="15dp"
android:layout_height="45dp"
android:layout_gravity="center_vertical"
tools:background="#F00"
/>
<ImageView
android:id="@+id/yourTrainDestinationColorBar"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_below="@id/yourTrainHeader"
android:src="@drawable/basic_rectangle" />
<!-- Holds the destination text and train info -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:padding="5dp"
>
<TextView
android:id="@+id/yourTrainDestinationText"
style="@style/DepartureDestinationText"
android:layout_below="@id/yourTrainHeader"
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
android:ellipsize="marquee"
android:singleLine="true" />
<TextView
android:id="@+id/yourTrainDestinationText"
style="@style/DepartureDestinationText"
android:ellipsize="marquee"
android:singleLine="true"
tools:text="Richmond"
/>
<ImageView
android:id="@+id/yourTrainBikeIcon"
style="@style/BikeIcon"
android:layout_below="@id/yourTrainHeader"
android:layout_toRightOf="@id/yourTrainDestinationText" />
<TextView
android:id="@+id/yourTrainTrainLengthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="9 cars, platform 2"
/>
<ImageView
android:id="@+id/yourTrainXferIcon"
style="@style/XferIcon"
android:layout_below="@id/yourTrainBikeIcon"
android:layout_toRightOf="@id/yourTrainDestinationText"
android:src="@drawable/xfer" />
</LinearLayout>
<TextView
android:id="@+id/yourTrainTrainLengthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/yourTrainDestinationText"
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
android:paddingLeft="5dp" />
<!-- Holds the bike icon and xfer icon -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<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
android:id="@+id/yourTrainDepartureCountdown"
style="@style/DepartureCountdownText"
android:layout_alignLeft="@id/yourTrainSection"
android:layout_alignRight="@id/yourTrainSection"
android:layout_below="@id/yourTrainTrainLengthText"
bart:tickInterval="1" />
bart:tickInterval="1"
tools:text="Leaves in 15 min, 20s (+8s)"
/>
<com.dougkeen.bart.controls.CountdownTextView
android:id="@+id/yourTrainArrivalCountdown"
style="@style/DepartureCountdownText"
android:layout_alignLeft="@id/yourTrainSection"
android:layout_alignRight="@id/yourTrainSection"
android:layout_below="@id/yourTrainDepartureCountdown"
android:ellipsize="end"
bart:tickInterval="5" />
bart:tickInterval="5"
tools:text="Arrives ~11:12 AM (20 mins)"
/>
</merge>
</LinearLayout>

View File

@ -92,18 +92,10 @@
<item name="android:gravity">center</item>
</style>
<style name="BikeIcon">
<style name="TrainInfoIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">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>
<item name="android:layout_margin">5dp</item>
</style>
</resources>