Add description card

This commit is contained in:
cepprice 2021-01-23 21:06:59 +05:00
parent dd5056737e
commit 101402a3c4
7 changed files with 302 additions and 15 deletions

View file

@ -449,6 +449,10 @@ public class GPXUtilities {
public String getArticleLang() { public String getArticleLang() {
return getExtensionsToRead().get("article_lang"); return getExtensionsToRead().get("article_lang");
} }
public String getDescription() {
return getExtensionsToRead().get("desc");
}
} }
public static class Author extends GPXExtensions { public static class Author extends GPXExtensions {

View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?attr/list_background_color">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/activity_background_basic">
<include layout="@layout/list_item_divider" />
</FrameLayout>
<net.osmand.plus.widgets.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:text="@string/shared_string_description"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/main_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/content_padding_small"
android:visibility="gone"
android:adjustViewBounds="true"
tools:visibility="visible"
tools:src="@drawable/img_help_announcement_time_day"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:lineSpacingMultiplier="1.1"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife."/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginBottom="@dimen/context_menu_padding_margin_small"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_read_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/context_menu_padding_margin_small"
android:layout_marginLeft="@dimen/context_menu_padding_margin_small"
android:layout_gravity="start"
android:gravity="center_vertical"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
android:paddingTop="@dimen/bottom_sheet_content_padding_small"
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableStartCompat="@drawable/ic_action_read_article"
osmand:drawableLeftCompat="@drawable/ic_action_read_article"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/context_menu_read_full"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/context_menu_padding_margin_small"
android:layout_marginEnd="@dimen/context_menu_padding_margin_small"
android:layout_gravity="end"
android:gravity="center_vertical"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableRightCompat="@drawable/ic_action_edit_dark"
osmand:drawableEndCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/shared_string_edit"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="0dp"-->
<!-- android:layout_weight="1"-->
<!-- android:orientation="vertical">-->
<!-- <include layout="@layout/card_bottom_divider"/>-->
<!-- <View-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="0dp"-->
<!-- android:minHeight="48dp"-->
<!-- android:layout_weight="1"-->
<!-- android:background="?attr/activity_background_basic"/>-->
<!-- <include layout="@layout/card_top_divider"/>-->
<!-- </LinearLayout>-->
</LinearLayout>

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <item-->
<!-- android:id="@+id/action_overview"--> <item
<!-- android:icon="@drawable/ic_action_trail_overview"--> android:id="@+id/action_overview"
<!-- android:title="@string/shared_string_overview" />--> android:icon="@drawable/ic_action_trail_overview"
android:title="@string/shared_string_overview" />
<item <item
android:id="@+id/action_track" android:id="@+id/action_track"

View file

@ -12,6 +12,8 @@
--> -->
<string name="context_menu_edit_descr">Edit description</string>
<string name="context_menu_read_full">Read full</string>
<string name="message_name_is_already_exists">The name is already exists</string> <string name="message_name_is_already_exists">The name is already exists</string>
<string name="message_server_error">Server error: %1$s</string> <string name="message_server_error">Server error: %1$s</string>
<string name="routing_engine_vehicle_type_mtb">MTB</string> <string name="routing_engine_vehicle_type_mtb">MTB</string>

View file

@ -196,4 +196,8 @@ public class FileUtils {
public interface RenameCallback { public interface RenameCallback {
void renamedTo(File file); void renamedTo(File file);
} }
public interface GpxEditedCallback {
void onGpxChanged();
}
} }

View file

@ -0,0 +1,110 @@
package net.osmand.plus.track;
import android.text.TextUtils;
import android.view.View;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PicassoUtils;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
public class DescriptionCard extends BaseCard {
private final GPXFile gpxFile;
public DescriptionCard(MapActivity mapActivity, GPXFile gpxFile) {
super(mapActivity);
this.gpxFile = gpxFile;
}
@Override
public int getCardLayoutId() {
return R.layout.gpx_description_preview_card;
}
@Override
protected void updateContent() {
final String title = gpxFile.metadata.getArticleTitle();
final String imageUrl = getMetadataImageLink(gpxFile.metadata);
final String descriptionHtml = gpxFile.metadata.getDescription();
setupImage(imageUrl);
TextViewEx tvDescription = view.findViewById(R.id.description);
tvDescription.setText(getFirstParagraph(descriptionHtml));
TextViewEx readBtn = view.findViewById(R.id.btn_read_full);
readBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
TextViewEx editBtn = view.findViewById(R.id.btn_edit);
editBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
@Nullable
private String getMetadataImageLink(@NonNull GPXUtilities.Metadata metadata) {
String link = metadata.link;
if (!TextUtils.isEmpty(link)) {
String lowerCaseLink = link.toLowerCase();
if (lowerCaseLink.contains(".jpg")
|| lowerCaseLink.contains(".jpeg")
|| lowerCaseLink.contains(".png")
|| lowerCaseLink.contains(".bmp")
|| lowerCaseLink.contains(".webp")) {
return link;
}
}
return null;
}
private String getFirstParagraph(String descriptionHtml) {
if (descriptionHtml != null) {
String firstParagraph = WikiArticleHelper.getPartialContent(descriptionHtml);
if (!TextUtils.isEmpty(firstParagraph)) {
return firstParagraph;
}
}
return descriptionHtml;
}
private void setupImage(final String imageUrl) {
if (imageUrl == null) {
return;
}
final PicassoUtils picasso = PicassoUtils.getPicasso(app);
RequestCreator rc = Picasso.get().load(imageUrl);
final AppCompatImageView image = view.findViewById(R.id.main_image);
rc.into(image, new Callback() {
@Override
public void onSuccess() {
picasso.setResultLoaded(imageUrl, true);
AndroidUiHelper.updateVisibility(image, true);
}
@Override
public void onError(Exception e) {
picasso.setResultLoaded(imageUrl, false);
}
});
}
}

View file

@ -15,19 +15,12 @@ import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.FileUtils; import net.osmand.FileUtils;
import net.osmand.FileUtils.GpxEditedCallback;
import net.osmand.FileUtils.RenameCallback; import net.osmand.FileUtils.RenameCallback;
import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.Track;
@ -79,6 +72,14 @@ import org.apache.commons.logging.Log;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected;
@ -96,7 +97,7 @@ import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX;
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener, public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener,
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener { SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, GpxEditedCallback {
public static final String TAG = TrackMenuFragment.class.getName(); public static final String TAG = TrackMenuFragment.class.getName();
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class); private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
@ -109,15 +110,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private TextView headerTitle; private TextView headerTitle;
private ImageView headerIcon; private ImageView headerIcon;
private BottomNavigationView bottomNav; private BottomNavigationView bottomNav;
private TrackMenuType menuType = TrackMenuType.TRACK; private TrackMenuType menuType = TrackMenuType.OVERVIEW;
private SegmentsCard segmentsCard; private SegmentsCard segmentsCard;
private OptionsCard optionsCard; private OptionsCard optionsCard;
private DescriptionCard descriptionCard;
private TrackChartPoints trackChartPoints; private TrackChartPoints trackChartPoints;
private int menuTitleHeight; private int menuTitleHeight;
public enum TrackMenuType { public enum TrackMenuType {
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
TRACK(R.id.action_track, R.string.shared_string_gpx_tracks), TRACK(R.id.action_track, R.string.shared_string_gpx_tracks),
POINTS(R.id.action_points, R.string.shared_string_gpx_points), POINTS(R.id.action_points, R.string.shared_string_gpx_points),
OPTIONS(R.id.action_options, R.string.shared_string_options); OPTIONS(R.id.action_options, R.string.shared_string_options);
@ -219,6 +222,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
} }
private void updateHeader() { private void updateHeader() {
ViewGroup headerContainer = (ViewGroup) routeMenuTopShadowAll;
if (descriptionCard != null && descriptionCard.getView() != null) {
headerContainer.removeView(descriptionCard.getView());
}
if (menuType == TrackMenuType.OPTIONS) { if (menuType == TrackMenuType.OPTIONS) {
headerTitle.setText(menuType.titleId); headerTitle.setText(menuType.titleId);
AndroidUiHelper.updateVisibility(headerIcon, false); AndroidUiHelper.updateVisibility(headerIcon, false);
@ -226,8 +233,18 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
String fileName = Algorithms.getFileWithoutDirs(getGpx().path); String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
headerTitle.setText(GpxUiHelper.getGpxTitle(fileName)); headerTitle.setText(GpxUiHelper.getGpxTitle(fileName));
AndroidUiHelper.updateVisibility(headerIcon, true); AndroidUiHelper.updateVisibility(headerIcon, true);
if (menuType == TrackMenuType.OVERVIEW) {
fillOverviewTab(headerContainer);
} }
} }
runLayoutListener();
headerContainer.post(new Runnable() {
@Override
public void run() {
openMenuScreen(menuType == TrackMenuType.OVERVIEW ? MenuState.HEADER_ONLY : MenuState.HALF_SCREEN, false);
}
});
}
private void setupCards() { private void setupCards() {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
@ -262,6 +279,19 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
} }
} }
private void fillOverviewTab(ViewGroup headerContainer) {
if (descriptionCard != null && descriptionCard.getView() != null) {
ViewGroup parent = ((ViewGroup) descriptionCard.getView().getParent());
if (parent != null) {
parent.removeView(descriptionCard.getView());
}
headerContainer.addView(descriptionCard.getView());
} else {
descriptionCard = new DescriptionCard(getMapActivity(), displayHelper.getGpx());
headerContainer.addView(descriptionCard.build(getMapActivity()));
}
}
@Override @Override
protected void calculateLayout(View view, boolean initLayout) { protected void calculateLayout(View view, boolean initLayout) {
menuTitleHeight = routeMenuTopShadowAll.getHeight() menuTitleHeight = routeMenuTopShadowAll.getHeight()
@ -306,6 +336,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null && trackChartPoints != null) { if (mapActivity != null && trackChartPoints != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
} }
updateHeader();
} }
@Override @Override
@ -567,7 +598,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
BottomNavigationView bottomNav = view.findViewById(R.id.bottom_navigation); BottomNavigationView bottomNav = view.findViewById(R.id.bottom_navigation);
bottomNav.setItemIconTintList(navColorStateList); bottomNav.setItemIconTintList(navColorStateList);
bottomNav.setItemTextColor(navColorStateList); bottomNav.setItemTextColor(navColorStateList);
bottomNav.setSelectedItemId(R.id.action_track); bottomNav.setSelectedItemId(R.id.action_overview);
bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) { public boolean onNavigationItemSelected(@NonNull MenuItem item) {
@ -783,6 +814,13 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
} }
} }
@Override
public void onGpxChanged() {
if (descriptionCard != null) {
descriptionCard.update();
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) { public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) {
try { try {
Bundle args = new Bundle(); Bundle args = new Bundle();