mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-11 13:33:07 +02:00
display photos in marker list
This commit is contained in:
@@ -24,9 +24,9 @@ limitations under the License.
|
|||||||
android:shrinkColumns="1"
|
android:shrinkColumns="1"
|
||||||
android:stretchColumns="1"
|
android:stretchColumns="1"
|
||||||
style="@style/ListItem" >
|
style="@style/ListItem" >
|
||||||
<TableRow
|
<!-- First row -->
|
||||||
android:layout_height="wrap_content"
|
<TableRow>
|
||||||
android:layout_width="match_parent" >
|
<!-- First column -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:contentDescription="@string/icon_track"
|
android:contentDescription="@string/icon_track"
|
||||||
android:id="@+id/list_item_icon"
|
android:id="@+id/list_item_icon"
|
||||||
@@ -35,39 +35,67 @@ limitations under the License.
|
|||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_width="wrap_content" />
|
android:layout_width="wrap_content" />
|
||||||
<TableLayout
|
<!-- Second column -->
|
||||||
|
<LinearLayout
|
||||||
|
android:baselineAligned="false"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent" >
|
||||||
android:shrinkColumns="0"
|
<LinearLayout
|
||||||
android:stretchColumns="0" >
|
android:layout_height="wrap_content"
|
||||||
<TableRow>
|
android:layout_weight="3"
|
||||||
<TextView
|
android:layout_width="0dp" >
|
||||||
android:id="@+id/list_item_name"
|
<TableLayout
|
||||||
android:layout_gravity="bottom"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="fill_parent"
|
android:layout_weight="1"
|
||||||
android:singleLine="true"
|
android:layout_width="0dp"
|
||||||
style="@style/TextMedium" />
|
android:shrinkColumns="*"
|
||||||
<TextView
|
android:stretchColumns="*" >
|
||||||
android:id="@+id/list_item_date"
|
<TableRow>
|
||||||
style="@style/ListItemDate" />
|
<TextView
|
||||||
</TableRow>
|
android:ellipsize="end"
|
||||||
<TableRow>
|
android:id="@+id/list_item_name"
|
||||||
<!-- Need to match the style set in ListItemUtils.setListItem -->
|
android:singleLine="true"
|
||||||
<TextView
|
style="@style/TextMedium" />
|
||||||
android:id="@+id/list_item_time_distance"
|
</TableRow>
|
||||||
android:layout_gravity="bottom"
|
<TableRow>
|
||||||
android:layout_width="fill_parent"
|
<!-- Need to match the style set in ListItemUtils.setListItem -->
|
||||||
android:singleLine="true"
|
<TextView
|
||||||
style="@style/TextSmall" />
|
android:ellipsize="end"
|
||||||
<TextView
|
android:id="@+id/list_item_time_distance"
|
||||||
android:id="@+id/list_item_time"
|
android:singleLine="true"
|
||||||
style="@style/ListItemDate" />
|
style="@style/TextSmall" />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/list_item_photo"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
</LinearLayout>
|
||||||
|
<TableLayout
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:shrinkColumns="*"
|
||||||
|
android:stretchColumns="*" >
|
||||||
|
<TableRow>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/list_item_date"
|
||||||
|
style="@style/ListItemDate" />
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/list_item_time"
|
||||||
|
style="@style/ListItemDate" />
|
||||||
|
</TableRow>
|
||||||
|
</TableLayout>
|
||||||
|
</LinearLayout>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow
|
<!-- Second row -->
|
||||||
android:layout_height="wrap_content"
|
<TableRow>
|
||||||
android:layout_width="match_parent" >
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/list_item_description"
|
android:id="@+id/list_item_description"
|
||||||
android:layout_column="1"
|
android:layout_column="1"
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ limitations under the License.
|
|||||||
android:id="@+id/marker_detail_waypoint_description"
|
android:id="@+id/marker_detail_waypoint_description"
|
||||||
style="@style/TextLarge.WithTopMargin" />
|
style="@style/TextLarge.WithTopMargin" />
|
||||||
<ImageView
|
<ImageView
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:id="@+id/marker_detail_waypoint_photo"
|
android:id="@+id/marker_detail_waypoint_photo"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
|
|||||||
@@ -23,14 +23,12 @@ import com.google.android.apps.mytracks.content.Waypoint.WaypointType;
|
|||||||
import com.google.android.apps.mytracks.fragments.DeleteMarkerDialogFragment;
|
import com.google.android.apps.mytracks.fragments.DeleteMarkerDialogFragment;
|
||||||
import com.google.android.apps.mytracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
|
import com.google.android.apps.mytracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller;
|
||||||
import com.google.android.apps.mytracks.util.IntentUtils;
|
import com.google.android.apps.mytracks.util.IntentUtils;
|
||||||
|
import com.google.android.apps.mytracks.util.PhotoUtils;
|
||||||
import com.google.android.apps.mytracks.util.StatsUtils;
|
import com.google.android.apps.mytracks.util.StatsUtils;
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.media.ExifInterface;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -41,8 +39,6 @@ import android.view.View;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity to display marker detail info.
|
* An activity to display marker detail info.
|
||||||
*
|
*
|
||||||
@@ -73,7 +69,7 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity implements De
|
|||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set waypoint, needed in onCreateOptionsMenu
|
// Set waypoint, needed in onCreateOptionsMenu
|
||||||
waypoint = myTracksProviderUtils.getWaypoint(markerId);
|
waypoint = myTracksProviderUtils.getWaypoint(markerId);
|
||||||
if (waypoint == null) {
|
if (waypoint == null) {
|
||||||
@@ -103,7 +99,7 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity implements De
|
|||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name.setText(getString(R.string.generic_name_line, waypoint.getName()));
|
name.setText(getString(R.string.generic_name_line, waypoint.getName()));
|
||||||
if (waypoint.getType() == WaypointType.WAYPOINT) {
|
if (waypoint.getType() == WaypointType.WAYPOINT) {
|
||||||
waypointSection.setVisibility(View.VISIBLE);
|
waypointSection.setVisibility(View.VISIBLE);
|
||||||
@@ -120,7 +116,11 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity implements De
|
|||||||
imageView.setVisibility(View.GONE);
|
imageView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
imageView.setVisibility(View.VISIBLE);
|
imageView.setVisibility(View.VISIBLE);
|
||||||
setImageVew(imageView, Uri.parse(photoUrl));
|
Display defaultDisplay = getWindowManager().getDefaultDisplay();
|
||||||
|
int displayWidth = defaultDisplay.getWidth();
|
||||||
|
int displayHeight = defaultDisplay.getHeight();
|
||||||
|
bitmap = PhotoUtils.setImageVew(
|
||||||
|
imageView, Uri.parse(photoUrl), displayWidth, displayHeight, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
waypointSection.setVisibility(View.GONE);
|
waypointSection.setVisibility(View.GONE);
|
||||||
@@ -190,107 +190,4 @@ public class MarkerDetailActivity extends AbstractMyTracksActivity implements De
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an image view.
|
|
||||||
*
|
|
||||||
* @param imageView the image view
|
|
||||||
* @param uri the image uri
|
|
||||||
*/
|
|
||||||
private void setImageVew(ImageView imageView, Uri uri) {
|
|
||||||
|
|
||||||
// Get the image dimensions
|
|
||||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
||||||
|
|
||||||
options.inJustDecodeBounds = true;
|
|
||||||
BitmapFactory.decodeFile(uri.getPath(), options);
|
|
||||||
|
|
||||||
// Set imageWidth and imageHeight based on image rotation
|
|
||||||
int rotation = getRotation(uri);
|
|
||||||
int imageWidth;
|
|
||||||
int imageHeight;
|
|
||||||
|
|
||||||
if (rotation == 0 || rotation == 180) {
|
|
||||||
imageWidth = options.outWidth;
|
|
||||||
imageHeight = options.outHeight;
|
|
||||||
} else {
|
|
||||||
imageWidth = options.outHeight;
|
|
||||||
imageHeight = options.outWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a scaled down version of the image
|
|
||||||
Display defaultDisplay = getWindowManager().getDefaultDisplay();
|
|
||||||
int displayWidth = defaultDisplay.getWidth();
|
|
||||||
int displayHeight = defaultDisplay.getHeight();
|
|
||||||
|
|
||||||
options.inJustDecodeBounds = false;
|
|
||||||
options.inSampleSize = getInSampleSize(imageWidth, imageHeight, displayWidth, displayHeight);
|
|
||||||
options.inPurgeable = true;
|
|
||||||
|
|
||||||
Bitmap scaledBitmap = BitmapFactory.decodeFile(uri.getPath(), options);
|
|
||||||
|
|
||||||
// Rotate the scaled down image
|
|
||||||
if (rotation == 0) {
|
|
||||||
bitmap = scaledBitmap;
|
|
||||||
} else {
|
|
||||||
Matrix matrix = new Matrix();
|
|
||||||
matrix.postRotate(rotation);
|
|
||||||
bitmap = Bitmap.createBitmap(
|
|
||||||
scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
|
|
||||||
scaledBitmap.recycle();
|
|
||||||
}
|
|
||||||
imageView.setImageBitmap(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the image rotation
|
|
||||||
*
|
|
||||||
* @param uri the image uri
|
|
||||||
*/
|
|
||||||
private int getRotation(Uri uri) {
|
|
||||||
try {
|
|
||||||
ExifInterface exifInterface = new ExifInterface(uri.getPath());
|
|
||||||
switch (exifInterface.getAttributeInt(
|
|
||||||
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
|
||||||
return 90;
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
|
||||||
return 180;
|
|
||||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
|
||||||
return 270;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to get photo orientation", e);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the in sample size.
|
|
||||||
*
|
|
||||||
* @param imageWidth the image width
|
|
||||||
* @param imageHeight the image height
|
|
||||||
* @param displayWidth the display width. Can be 0
|
|
||||||
* @param displayHeight the display height. Can be 0
|
|
||||||
*/
|
|
||||||
private int getInSampleSize(
|
|
||||||
int imageWidth, int imageHeight, int displayWidth, int displayHeight) {
|
|
||||||
int widthRatio = 1;
|
|
||||||
if (displayWidth != 0 && imageWidth > displayWidth) {
|
|
||||||
widthRatio = Math.round((float) imageWidth / (float) displayWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
int heightRatio = 1;
|
|
||||||
if (displayHeight != 0 && imageHeight > displayHeight) {
|
|
||||||
heightRatio = Math.round((float) imageHeight / (float) displayHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the larger sample ratio so the image will not be larger than the
|
|
||||||
* displayWidth and displayHeight.
|
|
||||||
*/
|
|
||||||
return Math.max(widthRatio, heightRatio);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class MarkerListActivity extends AbstractMyTracksActivity implements Dele
|
|||||||
|
|
||||||
private static final String[] PROJECTION = new String[] { WaypointsColumns._ID,
|
private static final String[] PROJECTION = new String[] { WaypointsColumns._ID,
|
||||||
WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY,
|
WaypointsColumns.NAME, WaypointsColumns.DESCRIPTION, WaypointsColumns.CATEGORY,
|
||||||
WaypointsColumns.TYPE, WaypointsColumns.TIME };
|
WaypointsColumns.TYPE, WaypointsColumns.TIME, WaypointsColumns.PHOTOURL };
|
||||||
|
|
||||||
// Callback when an item is selected in the contextual action mode
|
// Callback when an item is selected in the contextual action mode
|
||||||
private ContextualActionModeCallback
|
private ContextualActionModeCallback
|
||||||
@@ -173,19 +173,25 @@ public class MarkerListActivity extends AbstractMyTracksActivity implements Dele
|
|||||||
public void bindView(View view, Context context, Cursor cursor) {
|
public void bindView(View view, Context context, Cursor cursor) {
|
||||||
int typeIndex = cursor.getColumnIndex(WaypointsColumns.TYPE);
|
int typeIndex = cursor.getColumnIndex(WaypointsColumns.TYPE);
|
||||||
int nameIndex = cursor.getColumnIndex(WaypointsColumns.NAME);
|
int nameIndex = cursor.getColumnIndex(WaypointsColumns.NAME);
|
||||||
int categoryIndex = cursor.getColumnIndex(WaypointsColumns.CATEGORY);
|
int photoUrlIndex = cursor.getColumnIndex(WaypointsColumns.PHOTOURL);
|
||||||
int timeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TIME);
|
int timeIndex = cursor.getColumnIndexOrThrow(WaypointsColumns.TIME);
|
||||||
|
int categoryIndex = cursor.getColumnIndex(WaypointsColumns.CATEGORY);
|
||||||
int descriptionIndex = cursor.getColumnIndex(WaypointsColumns.DESCRIPTION);
|
int descriptionIndex = cursor.getColumnIndex(WaypointsColumns.DESCRIPTION);
|
||||||
|
|
||||||
boolean statistics = WaypointType.values()[cursor.getInt(typeIndex)]
|
boolean statistics = WaypointType.values()[cursor.getInt(typeIndex)]
|
||||||
== WaypointType.STATISTICS;
|
== WaypointType.STATISTICS;
|
||||||
int iconId = statistics ? R.drawable.ic_marker_yellow_pushpin
|
int iconId = statistics ? R.drawable.ic_marker_yellow_pushpin
|
||||||
: R.drawable.ic_marker_blue_pushpin;
|
: R.drawable.ic_marker_blue_pushpin;
|
||||||
|
String name = cursor.getString(nameIndex);
|
||||||
|
String sharedOwner = track.getSharedOwner();
|
||||||
|
String photoUrl = cursor.getString(photoUrlIndex);
|
||||||
|
long time = cursor.getLong(timeIndex);
|
||||||
String category = statistics ? null : cursor.getString(categoryIndex);
|
String category = statistics ? null : cursor.getString(categoryIndex);
|
||||||
String description = statistics ? null : cursor.getString(descriptionIndex);
|
String description = statistics ? null : cursor.getString(descriptionIndex);
|
||||||
|
|
||||||
ListItemUtils.setListItem(MarkerListActivity.this, view, false, true, iconId,
|
ListItemUtils.setListItem(MarkerListActivity.this, view, false, true, iconId,
|
||||||
R.string.icon_marker, cursor.getString(nameIndex), category, null, null,
|
R.string.icon_marker, name, sharedOwner, null, null, photoUrl, time, category,
|
||||||
cursor.getLong(timeIndex), description, track.getSharedOwner());
|
description);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
listView.setAdapter(resourceCursorAdapter);
|
listView.setAdapter(resourceCursorAdapter);
|
||||||
|
|||||||
@@ -83,12 +83,14 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
|||||||
private static final String ICON_ID_FIELD = "icon";
|
private static final String ICON_ID_FIELD = "icon";
|
||||||
private static final String ICON_CONTENT_DESCRIPTION_ID_FIELD = "iconContentDescription";
|
private static final String ICON_CONTENT_DESCRIPTION_ID_FIELD = "iconContentDescription";
|
||||||
private static final String NAME_FIELD = "name";
|
private static final String NAME_FIELD = "name";
|
||||||
private static final String CATEGORY_FIELD = "category";
|
private static final String SHARED_OWNER_FIELD = "sharedOwner";
|
||||||
private static final String TOTAL_TIME_FIELD = "totalTime";
|
private static final String TOTAL_TIME_FIELD = "totalTime";
|
||||||
private static final String TOTAL_DISTANCE_FIELD = "totalDistance";
|
private static final String TOTAL_DISTANCE_FIELD = "totalDistance";
|
||||||
|
private static final String PHOTO_URL_FIELD = "photoUrl";
|
||||||
private static final String START_TIME_FIELD = "startTime";
|
private static final String START_TIME_FIELD = "startTime";
|
||||||
|
private static final String CATEGORY_FIELD = "category";
|
||||||
private static final String DESCRIPTION_FIELD = "description";
|
private static final String DESCRIPTION_FIELD = "description";
|
||||||
private static final String SHARED_OWNER_FIELD = "sharedOwner";
|
|
||||||
private static final String TRACK_ID_FIELD = "trackId";
|
private static final String TRACK_ID_FIELD = "trackId";
|
||||||
private static final String MARKER_ID_FIELD = "markerId";
|
private static final String MARKER_ID_FIELD = "markerId";
|
||||||
|
|
||||||
@@ -228,15 +230,17 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
|||||||
int iconId = (Integer) resultMap.get(ICON_ID_FIELD);
|
int iconId = (Integer) resultMap.get(ICON_ID_FIELD);
|
||||||
int iconContentDescriptionId = (Integer) resultMap.get(ICON_CONTENT_DESCRIPTION_ID_FIELD);
|
int iconContentDescriptionId = (Integer) resultMap.get(ICON_CONTENT_DESCRIPTION_ID_FIELD);
|
||||||
String name = (String) resultMap.get(NAME_FIELD);
|
String name = (String) resultMap.get(NAME_FIELD);
|
||||||
String category = (String) resultMap.get(CATEGORY_FIELD);
|
String sharedOwner = (String) resultMap.get(SHARED_OWNER_FIELD);
|
||||||
String totalTime = (String) resultMap.get(TOTAL_TIME_FIELD);
|
String totalTime = (String) resultMap.get(TOTAL_TIME_FIELD);
|
||||||
String totalDistance = (String) resultMap.get(TOTAL_DISTANCE_FIELD);
|
String totalDistance = (String) resultMap.get(TOTAL_DISTANCE_FIELD);
|
||||||
|
String photoUrl = (String) resultMap.get(PHOTO_URL_FIELD);
|
||||||
Long startTime = (Long) resultMap.get(START_TIME_FIELD);
|
Long startTime = (Long) resultMap.get(START_TIME_FIELD);
|
||||||
|
String category = (String) resultMap.get(CATEGORY_FIELD);
|
||||||
String description = (String) resultMap.get(DESCRIPTION_FIELD);
|
String description = (String) resultMap.get(DESCRIPTION_FIELD);
|
||||||
String sharedOwner = (String) resultMap.get(SHARED_OWNER_FIELD);
|
|
||||||
ListItemUtils.setListItem(SearchListActivity.this, view, isRecording, isPaused, iconId,
|
ListItemUtils.setListItem(SearchListActivity.this, view, isRecording, isPaused, iconId,
|
||||||
iconContentDescriptionId, name, category, totalTime, totalDistance, startTime,
|
iconContentDescriptionId, name, sharedOwner, totalTime, totalDistance, photoUrl,
|
||||||
description, sharedOwner);
|
startTime, category, description);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -487,14 +491,15 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
|||||||
statistics ? R.drawable.ic_marker_yellow_pushpin : R.drawable.ic_marker_blue_pushpin);
|
statistics ? R.drawable.ic_marker_yellow_pushpin : R.drawable.ic_marker_blue_pushpin);
|
||||||
resultMap.put(ICON_CONTENT_DESCRIPTION_ID_FIELD, R.string.icon_marker);
|
resultMap.put(ICON_CONTENT_DESCRIPTION_ID_FIELD, R.string.icon_marker);
|
||||||
resultMap.put(NAME_FIELD, waypoint.getName());
|
resultMap.put(NAME_FIELD, waypoint.getName());
|
||||||
resultMap.put(CATEGORY_FIELD, statistics ? null : waypoint.getCategory());
|
resultMap.put(SHARED_OWNER_FIELD, sharedOwner);
|
||||||
// Display the marker's track name in the total time field
|
// Display the marker's track name in the total time field
|
||||||
resultMap.put(TOTAL_TIME_FIELD, trackName == null ? null
|
resultMap.put(TOTAL_TIME_FIELD, trackName == null ? null
|
||||||
: getString(R.string.search_list_marker_track_location, trackName));
|
: getString(R.string.search_list_marker_track_location, trackName));
|
||||||
resultMap.put(TOTAL_DISTANCE_FIELD, null);
|
resultMap.put(TOTAL_DISTANCE_FIELD, null);
|
||||||
|
resultMap.put(PHOTO_URL_FIELD, waypoint.getPhotoUrl());
|
||||||
resultMap.put(START_TIME_FIELD, waypoint.getLocation().getTime());
|
resultMap.put(START_TIME_FIELD, waypoint.getLocation().getTime());
|
||||||
|
resultMap.put(CATEGORY_FIELD, statistics ? null : waypoint.getCategory());
|
||||||
resultMap.put(DESCRIPTION_FIELD, statistics ? null : waypoint.getDescription());
|
resultMap.put(DESCRIPTION_FIELD, statistics ? null : waypoint.getDescription());
|
||||||
resultMap.put(SHARED_OWNER_FIELD, sharedOwner);
|
|
||||||
resultMap.put(TRACK_ID_FIELD, waypoint.getTrackId());
|
resultMap.put(TRACK_ID_FIELD, waypoint.getTrackId());
|
||||||
resultMap.put(MARKER_ID_FIELD, waypoint.getId());
|
resultMap.put(MARKER_ID_FIELD, waypoint.getId());
|
||||||
}
|
}
|
||||||
@@ -515,13 +520,14 @@ public class SearchListActivity extends AbstractSendToGoogleActivity implements
|
|||||||
resultMap.put(ICON_ID_FIELD, TrackIconUtils.getIconDrawable(icon));
|
resultMap.put(ICON_ID_FIELD, TrackIconUtils.getIconDrawable(icon));
|
||||||
resultMap.put(ICON_CONTENT_DESCRIPTION_ID_FIELD, R.string.icon_track);
|
resultMap.put(ICON_CONTENT_DESCRIPTION_ID_FIELD, R.string.icon_track);
|
||||||
resultMap.put(NAME_FIELD, track.getName());
|
resultMap.put(NAME_FIELD, track.getName());
|
||||||
resultMap.put(CATEGORY_FIELD, category);
|
resultMap.put(SHARED_OWNER_FIELD, track.getSharedOwner());
|
||||||
resultMap.put(TOTAL_TIME_FIELD, StringUtils.formatElapsedTime(tripStatitics.getTotalTime()));
|
resultMap.put(TOTAL_TIME_FIELD, StringUtils.formatElapsedTime(tripStatitics.getTotalTime()));
|
||||||
resultMap.put(TOTAL_DISTANCE_FIELD,
|
resultMap.put(TOTAL_DISTANCE_FIELD,
|
||||||
StringUtils.formatDistance(this, tripStatitics.getTotalDistance(), metricUnits));
|
StringUtils.formatDistance(this, tripStatitics.getTotalDistance(), metricUnits));
|
||||||
|
resultMap.put(PHOTO_URL_FIELD, null);
|
||||||
resultMap.put(START_TIME_FIELD, tripStatitics.getStartTime());
|
resultMap.put(START_TIME_FIELD, tripStatitics.getStartTime());
|
||||||
|
resultMap.put(CATEGORY_FIELD, category);
|
||||||
resultMap.put(DESCRIPTION_FIELD, track.getDescription());
|
resultMap.put(DESCRIPTION_FIELD, track.getDescription());
|
||||||
resultMap.put(SHARED_OWNER_FIELD, track.getSharedOwner());
|
|
||||||
resultMap.put(TRACK_ID_FIELD, track.getId());
|
resultMap.put(TRACK_ID_FIELD, track.getId());
|
||||||
resultMap.put(MARKER_ID_FIELD, null);
|
resultMap.put(MARKER_ID_FIELD, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -361,28 +361,28 @@ public class TrackListActivity extends AbstractSendToGoogleActivity
|
|||||||
int idIndex = cursor.getColumnIndex(TracksColumns._ID);
|
int idIndex = cursor.getColumnIndex(TracksColumns._ID);
|
||||||
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
|
int iconIndex = cursor.getColumnIndex(TracksColumns.ICON);
|
||||||
int nameIndex = cursor.getColumnIndex(TracksColumns.NAME);
|
int nameIndex = cursor.getColumnIndex(TracksColumns.NAME);
|
||||||
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
int sharedOwnerIndex = cursor.getColumnIndex(TracksColumns.SHAREDOWNER);
|
||||||
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
|
int totalTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALTIME);
|
||||||
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
|
int totalDistanceIndex = cursor.getColumnIndexOrThrow(TracksColumns.TOTALDISTANCE);
|
||||||
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
|
int startTimeIndex = cursor.getColumnIndexOrThrow(TracksColumns.STARTTIME);
|
||||||
|
int categoryIndex = cursor.getColumnIndex(TracksColumns.CATEGORY);
|
||||||
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
int descriptionIndex = cursor.getColumnIndex(TracksColumns.DESCRIPTION);
|
||||||
int sharedOwnerIndex = cursor.getColumnIndex(TracksColumns.SHAREDOWNER);
|
|
||||||
|
|
||||||
boolean isRecording = cursor.getLong(idIndex) == recordingTrackId;
|
boolean isRecording = cursor.getLong(idIndex) == recordingTrackId;
|
||||||
String icon = cursor.getString(iconIndex);
|
String icon = cursor.getString(iconIndex);
|
||||||
int iconId = TrackIconUtils.getIconDrawable(icon);
|
int iconId = TrackIconUtils.getIconDrawable(icon);
|
||||||
String name = cursor.getString(nameIndex);
|
String name = cursor.getString(nameIndex);
|
||||||
String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex);
|
String sharedOwner = cursor.getString(sharedOwnerIndex);
|
||||||
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
|
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
|
||||||
String totalDistance = StringUtils.formatDistance(
|
String totalDistance = StringUtils.formatDistance(
|
||||||
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
|
TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
|
||||||
long startTime = cursor.getLong(startTimeIndex);
|
long startTime = cursor.getLong(startTimeIndex);
|
||||||
|
String category = icon != null && !icon.equals("") ? null : cursor.getString(categoryIndex);
|
||||||
String description = cursor.getString(descriptionIndex);
|
String description = cursor.getString(descriptionIndex);
|
||||||
String sharedOwner = cursor.getString(sharedOwnerIndex);
|
|
||||||
|
|
||||||
ListItemUtils.setListItem(TrackListActivity.this, view, isRecording, recordingTrackPaused,
|
ListItemUtils.setListItem(TrackListActivity.this, view, isRecording, recordingTrackPaused,
|
||||||
iconId, R.string.icon_track, name, category, totalTime, totalDistance, startTime,
|
iconId, R.string.icon_track, name, sharedOwner, totalTime, totalDistance, null,
|
||||||
description, sharedOwner);
|
startTime, category, description);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
listView.setAdapter(sectionResourceCursorAdapter);
|
listView.setAdapter(sectionResourceCursorAdapter);
|
||||||
|
|||||||
@@ -18,8 +18,11 @@ package com.google.android.apps.mytracks.util;
|
|||||||
|
|
||||||
import com.google.android.maps.mytracks.R;
|
import com.google.android.maps.mytracks.R;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -38,23 +41,25 @@ public class ListItemUtils {
|
|||||||
/**
|
/**
|
||||||
* Sets a list item.
|
* Sets a list item.
|
||||||
*
|
*
|
||||||
* @param context the context
|
* @param activity the activity
|
||||||
* @param view the list item view
|
* @param view the list item view
|
||||||
* @param isRecording true if recording
|
* @param isRecording true if recording
|
||||||
* @param isPaused true if paused
|
* @param isPaused true if paused
|
||||||
* @param name the name value
|
|
||||||
* @param iconId the icon id
|
* @param iconId the icon id
|
||||||
* @param iconContentDescriptionId the icon content description id
|
* @param iconContentDescriptionId the icon content description id
|
||||||
* @param category the category value
|
* @param name the name value
|
||||||
|
* @param sharedOwner if shared with me track, the owner, else null
|
||||||
* @param totalTime the total time value
|
* @param totalTime the total time value
|
||||||
* @param totalDistance the total distance value
|
* @param totalDistance the total distance value
|
||||||
|
* @param photoUrl the photo url
|
||||||
* @param startTime the start time value
|
* @param startTime the start time value
|
||||||
|
* @param category the category value
|
||||||
* @param description the description value
|
* @param description the description value
|
||||||
* @param sharedOwner if shared with me track, the owner, else null
|
|
||||||
*/
|
*/
|
||||||
public static void setListItem(Context context, View view, boolean isRecording, boolean isPaused,
|
public static void setListItem(Activity activity, View view, boolean isRecording,
|
||||||
int iconId, int iconContentDescriptionId, String name, String category, String totalTime,
|
boolean isPaused, int iconId, int iconContentDescriptionId, String name, String sharedOwner,
|
||||||
String totalDistance, long startTime, String description, String sharedOwner) {
|
String totalTime, String totalDistance, String photoUrl, long startTime, String category,
|
||||||
|
String description) {
|
||||||
|
|
||||||
if (isRecording) {
|
if (isRecording) {
|
||||||
iconId = isPaused ? R.drawable.ic_track_paused : R.drawable.ic_track_recording;
|
iconId = isPaused ? R.drawable.ic_track_paused : R.drawable.ic_track_recording;
|
||||||
@@ -64,32 +69,47 @@ public class ListItemUtils {
|
|||||||
|
|
||||||
ImageView iconImageView = (ImageView) view.findViewById(R.id.list_item_icon);
|
ImageView iconImageView = (ImageView) view.findViewById(R.id.list_item_icon);
|
||||||
iconImageView.setImageResource(iconId);
|
iconImageView.setImageResource(iconId);
|
||||||
iconImageView.setContentDescription(context.getString(iconContentDescriptionId));
|
iconImageView.setContentDescription(activity.getString(iconContentDescriptionId));
|
||||||
|
|
||||||
|
// Set name
|
||||||
TextView nameTextView = (TextView) view.findViewById(R.id.list_item_name);
|
TextView nameTextView = (TextView) view.findViewById(R.id.list_item_name);
|
||||||
nameTextView.setText(name);
|
nameTextView.setText(name);
|
||||||
|
|
||||||
|
// Set sharedOwner/totalTime/totalDistance
|
||||||
TextView timeDistanceTextView = (TextView) view.findViewById(R.id.list_item_time_distance);
|
TextView timeDistanceTextView = (TextView) view.findViewById(R.id.list_item_time_distance);
|
||||||
if (isRecording) {
|
if (isRecording) {
|
||||||
timeDistanceTextView.setTextColor(context.getResources()
|
timeDistanceTextView.setTextColor(activity.getResources()
|
||||||
.getColor(isPaused ? android.R.color.white : R.color.recording_text));
|
.getColor(isPaused ? android.R.color.white : R.color.recording_text));
|
||||||
} else {
|
} else {
|
||||||
// Need to match the style set in list_item.xml
|
// Need to match the style set in list_item.xml
|
||||||
timeDistanceTextView.setTextAppearance(context, R.style.TextSmall);
|
timeDistanceTextView.setTextAppearance(activity, R.style.TextSmall);
|
||||||
}
|
}
|
||||||
setTextView(timeDistanceTextView,
|
setTextView(timeDistanceTextView,
|
||||||
getTimeDistance(context, isRecording, isPaused, sharedOwner, totalTime, totalDistance),
|
getTimeDistance(activity, isRecording, isPaused, sharedOwner, totalTime, totalDistance));
|
||||||
View.INVISIBLE);
|
|
||||||
|
|
||||||
String[] startTimeDisplay = getStartTime(isRecording, context, startTime);
|
// Set photoUrl
|
||||||
|
ImageView photo = (ImageView) view.findViewById(R.id.list_item_photo);
|
||||||
|
if (photoUrl == null || photoUrl.equals("")) {
|
||||||
|
photo.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
photo.setVisibility(View.VISIBLE);
|
||||||
|
Display defaultDisplay = activity.getWindowManager().getDefaultDisplay();
|
||||||
|
// Set the initial width to 35% of the display width
|
||||||
|
int width = (int) (defaultDisplay.getWidth() * .35);
|
||||||
|
PhotoUtils.setImageVew(photo, Uri.parse(photoUrl), width, 0, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set date/time
|
||||||
|
String[] startTimeDisplay = getStartTime(isRecording, activity, startTime);
|
||||||
TextView dateTextView = (TextView) view.findViewById(R.id.list_item_date);
|
TextView dateTextView = (TextView) view.findViewById(R.id.list_item_date);
|
||||||
setTextView(dateTextView, startTimeDisplay[0], View.GONE);
|
setTextView(dateTextView, startTimeDisplay[0]);
|
||||||
|
|
||||||
TextView timeTextView = (TextView) view.findViewById(R.id.list_item_time);
|
TextView timeTextView = (TextView) view.findViewById(R.id.list_item_time);
|
||||||
setTextView(timeTextView, startTimeDisplay[1], View.GONE);
|
setTextView(timeTextView, startTimeDisplay[1]);
|
||||||
|
|
||||||
|
// Set category/description
|
||||||
TextView descriptionTextView = (TextView) view.findViewById(R.id.list_item_description);
|
TextView descriptionTextView = (TextView) view.findViewById(R.id.list_item_description);
|
||||||
setTextView(descriptionTextView, getDescription(isRecording, category, description), View.GONE);
|
setTextView(descriptionTextView, getDescription(isRecording, category, description));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,11 +214,10 @@ public class ListItemUtils {
|
|||||||
*
|
*
|
||||||
* @param textView the text view
|
* @param textView the text view
|
||||||
* @param value the value for the text view
|
* @param value the value for the text view
|
||||||
* @param visibility visibility when value is not available
|
|
||||||
*/
|
*/
|
||||||
private static void setTextView(TextView textView, String value, int visibility) {
|
private static void setTextView(TextView textView, String value) {
|
||||||
if (value == null || value.length() == 0) {
|
if (value == null || value.length() == 0) {
|
||||||
textView.setVisibility(visibility);
|
textView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
textView.setVisibility(View.VISIBLE);
|
textView.setVisibility(View.VISIBLE);
|
||||||
textView.setText(value);
|
textView.setText(value);
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.apps.mytracks.util;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.media.ExifInterface;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for photos.
|
||||||
|
*
|
||||||
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
public class PhotoUtils {
|
||||||
|
|
||||||
|
private static final String TAG = PhotoUtils.class.getSimpleName();
|
||||||
|
|
||||||
|
private PhotoUtils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an image view.
|
||||||
|
*
|
||||||
|
* @param imageView the image view
|
||||||
|
* @param uri the image uri
|
||||||
|
* @param displayWidth the display width
|
||||||
|
* @param displayHeight the display height
|
||||||
|
* @param fitWithIn true to fit within the display area. False to crop and fill
|
||||||
|
* the display area.
|
||||||
|
*/
|
||||||
|
public static Bitmap setImageVew(
|
||||||
|
ImageView imageView, Uri uri, int displayWidth, int displayHeight, boolean fitWithIn) {
|
||||||
|
|
||||||
|
// Get the image dimensions
|
||||||
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
|
|
||||||
|
options.inJustDecodeBounds = true;
|
||||||
|
BitmapFactory.decodeFile(uri.getPath(), options);
|
||||||
|
|
||||||
|
// Set targetWidth and targetHeight
|
||||||
|
int targetWidth = displayWidth;
|
||||||
|
int targetHeight = displayHeight;
|
||||||
|
if (targetHeight == 0) {
|
||||||
|
targetHeight = (int) (targetWidth * ((float) options.outHeight / (float) options.outWidth));
|
||||||
|
imageView.getLayoutParams().height = targetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set imageWidth and imageHeight based on image rotation
|
||||||
|
int rotation = getRotation(uri);
|
||||||
|
int imageWidth;
|
||||||
|
int imageHeight;
|
||||||
|
|
||||||
|
if (rotation == 0 || rotation == 180) {
|
||||||
|
imageWidth = options.outWidth;
|
||||||
|
imageHeight = options.outHeight;
|
||||||
|
} else {
|
||||||
|
imageWidth = options.outHeight;
|
||||||
|
imageHeight = options.outWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a scaled down version of the image
|
||||||
|
options.inJustDecodeBounds = false;
|
||||||
|
options.inSampleSize = getInSampleSize(
|
||||||
|
imageWidth, imageHeight, targetWidth, targetHeight, fitWithIn);
|
||||||
|
options.inPurgeable = true;
|
||||||
|
|
||||||
|
Bitmap scaledBitmap = BitmapFactory.decodeFile(uri.getPath(), options);
|
||||||
|
|
||||||
|
// Get the final bitmap after rotating the scaled down image
|
||||||
|
Bitmap bitmap;
|
||||||
|
if (rotation == 0) {
|
||||||
|
bitmap = scaledBitmap;
|
||||||
|
} else {
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
matrix.postRotate(rotation);
|
||||||
|
bitmap = Bitmap.createBitmap(
|
||||||
|
scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
|
||||||
|
scaledBitmap.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
imageView.setImageBitmap(bitmap);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the image rotation
|
||||||
|
*
|
||||||
|
* @param uri the image uri
|
||||||
|
*/
|
||||||
|
private static int getRotation(Uri uri) {
|
||||||
|
try {
|
||||||
|
ExifInterface exifInterface = new ExifInterface(uri.getPath());
|
||||||
|
switch (exifInterface.getAttributeInt(
|
||||||
|
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
return 90;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
return 180;
|
||||||
|
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
return 270;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Unable to get photo orientation", e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the in sample size.
|
||||||
|
*
|
||||||
|
* @param imageWidth the image width
|
||||||
|
* @param imageHeight the image height
|
||||||
|
* @param targetWidth the target width
|
||||||
|
* @param targetHeight the target height
|
||||||
|
* @param fitWithin true to fit within the target area. False to crop and fill
|
||||||
|
* all target area.
|
||||||
|
*/
|
||||||
|
private static int getInSampleSize(
|
||||||
|
int imageWidth, int imageHeight, int targetWidth, int targetHeight, boolean fitWithin) {
|
||||||
|
float widthRatio = 1;
|
||||||
|
if (imageWidth > targetWidth) {
|
||||||
|
widthRatio = (float) imageWidth / (float) targetWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
float heightRatio = 1;
|
||||||
|
if (imageHeight > targetHeight) {
|
||||||
|
heightRatio = (float) imageHeight / (float) targetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To fit within the target area, return the larger sample ratio so the
|
||||||
|
* image will not be larger than the target dimensions. To crop and fill the
|
||||||
|
* target area, return the smaller sample ratio so the image will be greater
|
||||||
|
* than the target dimensions. Use Math.floor to not under sample.
|
||||||
|
*/
|
||||||
|
return (int) Math.floor(
|
||||||
|
fitWithin ? Math.max(widthRatio, heightRatio) : Math.min(widthRatio, heightRatio));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user