diff --git a/build.gradle b/build.gradle
index ecafae418..ee59d9229 100644
--- a/build.gradle
+++ b/build.gradle
@@ -100,4 +100,5 @@ dependencies {
testImplementation 'androidx.test:core:1.2.0'
testImplementation 'org.mockito:mockito-core:3.0.0'
+ implementation 'com.google.android.material:material:1.0.0'
}
diff --git a/src/main/java/de/dennisguse/opentracks/TabsAdapter.java b/src/main/java/de/dennisguse/opentracks/TabsAdapter.java
deleted file mode 100644
index 2e0aa2cf3..000000000
--- a/src/main/java/de/dennisguse/opentracks/TabsAdapter.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2013q 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 de.dennisguse.opentracks;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TabHost;
-import android.widget.TabHost.TabContentFactory;
-import android.widget.TabWidget;
-
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentPagerAdapter;
-import androidx.viewpager.widget.ViewPager;
-
-import java.util.ArrayList;
-
-/**
- * This is a helper class that implements the management of tabs and all details
- * of connecting a ViewPager with associated TabHost. It relies on a trick.
- * Normally a tab host has a simple API for supplying a View or Intent that each
- * tab will show. This is not sufficient for switching between pages. So instead
- * we make the content part of the tab host 0dp high (it is not shown) and the
- * TabsAdapter supplies its own dummy view to show as the tab content. It
- * listens to changes in tabs, and takes care of switch to the correct paged in
- * the ViewPager whenever the selected tab changes.
- *
- * Copied from the FragmentTabsPager sample in the support library.
- *
- * @author Jimmy Shih
- */
-//TODO Rework or better remove.
-public class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
-
- private final Context context;
- private final TabHost tabHost;
- private final ViewPager viewPager;
- private final ArrayList tabInfos = new ArrayList<>();
-
- public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager viewPager) {
- super(activity.getSupportFragmentManager());
- this.context = activity;
- this.tabHost = tabHost;
- this.viewPager = viewPager;
- this.tabHost.setOnTabChangedListener(this);
- this.viewPager.setAdapter(this);
- this.viewPager.setOnPageChangeListener(this);
- }
-
- public void addTab(TabHost.TabSpec tabSpec, Class> clss, Bundle bundle) {
- tabSpec.setContent(new DummyTabFactory(context));
-
- TabInfo info = new TabInfo(clss, bundle);
-
- tabInfos.add(info);
- tabHost.addTab(tabSpec);
- notifyDataSetChanged();
- }
-
- @Override
- public int getCount() {
- return tabInfos.size();
- }
-
- @Override
- @NonNull
- public Fragment getItem(int position) {
- TabInfo info = tabInfos.get(position);
- return Fragment.instantiate(context, info.clss.getName(), info.bundle);
- }
-
- @Override
- public void onTabChanged(String tabId) {
- int position = tabHost.getCurrentTab();
- viewPager.setCurrentItem(position);
- }
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- }
-
- @Override
- public void onPageSelected(int position) {
- /*
- * Unfortunately when TabHost changes the current tab, it kindly also takes care of putting focus on it when not in touch mode.
- * The jerk. This hack tries to prevent this from pulling focus out of our ViewPager.
- */
- TabWidget tabWidget = tabHost.getTabWidget();
- int oldFocusability = tabWidget.getDescendantFocusability();
- tabWidget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- tabHost.setCurrentTab(position);
- tabWidget.setDescendantFocusability(oldFocusability);
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
-
- /**
- * An object to hold a tab's info.
- *
- * @author Jimmy Shih
- */
- private static final class TabInfo {
-
- private final Class> clss;
- private final Bundle bundle;
-
- TabInfo(Class> clss, Bundle bundle) {
- this.clss = clss;
- this.bundle = bundle;
- }
- }
-
- /**
- * A dummy {@link TabContentFactory} that creates an empty view to satisfy the {@link TabHost} API.
- *
- * @author Jimmy Shih
- */
- private static class DummyTabFactory implements TabHost.TabContentFactory {
-
- private final Context context;
-
- DummyTabFactory(Context context) {
- this.context = context;
- }
-
- @Override
- public View createTabContent(String tag) {
- View view = new View(context);
- view.setMinimumWidth(0);
- view.setMinimumHeight(0);
- return view;
- }
- }
-}
diff --git a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
index d3920fbff..78bef7925 100644
--- a/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
+++ b/src/main/java/de/dennisguse/opentracks/TrackDetailActivity.java
@@ -31,14 +31,17 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
-import android.widget.TabHost;
-import android.widget.TabHost.TabSpec;
import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
+import com.google.android.material.tabs.TabLayout;
+
import de.dennisguse.opentracks.content.ContentProviderUtils;
import de.dennisguse.opentracks.content.Track;
import de.dennisguse.opentracks.content.TrackDataHub;
@@ -86,7 +89,7 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
private SharedPreferences sharedPreferences;
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackDataHub trackDataHub;
- private TabHost tabHost;
+ private ViewPager pager;
private TrackController trackController;
// From intent
@@ -202,28 +205,46 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
trackRecordingServiceConnection = new TrackRecordingServiceConnection(this, bindChangedCallback);
trackDataHub = TrackDataHub.newInstance(this);
- tabHost = findViewById(R.id.tackdetail_tabhost);
- tabHost.setup();
+ FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager(), 1) {
+ @Override
+ public int getCount() {
+ return 3;
+ }
- ViewPager viewPager = findViewById(R.id.pager);
- TabsAdapter tabsAdapter = new TabsAdapter(this, tabHost, viewPager);
-
- TabSpec statsTabSpec = tabHost.newTabSpec(StatsFragment.STATS_FRAGMENT_TAG).setIndicator(getString(R.string.track_detail_stats_tab));
- tabsAdapter.addTab(statsTabSpec, StatsFragment.class, null);
-
- TabSpec chartTimeTabSpec = tabHost.newTabSpec(ChartTimeFragment.CHART_FRAGMENT_TAG).setIndicator(getString(R.string.settings_chart_by_time));
- tabsAdapter.addTab(chartTimeTabSpec, ChartTimeFragment.class, null);
-
- TabSpec chartDistanceTabSpec = tabHost.newTabSpec(ChartDistanceFragment.CHART_FRAGMENT_TAG).setIndicator(getString(R.string.settings_chart_by_distance));
- tabsAdapter.addTab(chartDistanceTabSpec, ChartDistanceFragment.class, null);
+ @NonNull
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case 0:
+ return new StatsFragment();
+ case 1:
+ return new ChartTimeFragment();
+ case 2:
+ return new ChartDistanceFragment();
+ }
+ return null;
+ }
+ @Nullable
+ @Override
+ public CharSequence getPageTitle(int position) {
+ switch (position) {
+ case 0:
+ return getString(R.string.track_detail_stats_tab);
+ case 1:
+ return getString(R.string.settings_chart_by_time);
+ case 2:
+ return getString(R.string.settings_chart_by_distance);
+ }
+ return "Unknown Tab";
+ }
+ };
+ pager = findViewById(R.id.track_detail_activity_view_pager);
+ pager.setAdapter(adapter);
+ TabLayout tabs = findViewById(R.id.track_detail_activity_tablayout);
+ tabs.setupWithViewPager(pager);
if (savedInstanceState != null) {
- tabHost.setCurrentTabByTag(savedInstanceState.getString(CURRENT_TAB_TAG_KEY));
- }
-
- // Set the background after all three tabs are added
- for (int i = 0; i < tabHost.getTabWidget().getChildCount(); i++) {
- tabHost.getTabWidget().getChildAt(i).setBackgroundResource(R.drawable.tab_indicator);
+ pager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
}
trackController = new TrackController(this, trackRecordingServiceConnection, false, recordListener, stopListener);
@@ -298,7 +319,8 @@ public class TrackDetailActivity extends AbstractListActivity implements ChooseA
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putString(CURRENT_TAB_TAG_KEY, tabHost.getCurrentTabTag());
+ outState.putInt(CURRENT_TAB_TAG_KEY, pager.getCurrentItem());
+
if (photoUri != null) {
outState.putParcelable(PHOTO_URI_KEY, photoUri);
}
diff --git a/src/main/res/layout/track_detail.xml b/src/main/res/layout/track_detail.xml
index 16f24f20b..da16e02b7 100644
--- a/src/main/res/layout/track_detail.xml
+++ b/src/main/res/layout/track_detail.xml
@@ -14,20 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
+
-
-
-
+ android:layout_weight="1" />
\ No newline at end of file
diff --git a/src/main/res/layout/track_details_tab.xml b/src/main/res/layout/track_details_tab.xml
deleted file mode 100644
index 98fe4c675..000000000
--- a/src/main/res/layout/track_details_tab.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/res/values/do_not_translate.xml b/src/main/res/values/do_not_translate.xml
index 0afe48518..9fec1daee 100644
--- a/src/main/res/values/do_not_translate.xml
+++ b/src/main/res/values/do_not_translate.xml
@@ -17,7 +17,10 @@ limitations under the License.
https://github.com/dennisguse/opentracks
- Google\'s androidX support (Apache License, Version 2.0)
+
+ Google\'s androidX support (Apache License, Version 2.0) \n
+ Material Components for Android (Apache License, Version 2.0)
+
http://maps.google.com/mapfiles/ms/micons/ylw-pushpin.png
http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png