mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Migrate ViewPager usages to ViewPager2
Also migrate from FragmentStatePagerAdapter to FragmentStateAdapter, preserving the getPageTitle method for compatibility. Layouts needs adjustments since the TabLayout cannot be a child of ViewPager2. Further no subclassing is possible hence NonSwipeableViewPager has to be deleted, but the functionality is retained. Custom classes to handle FragmentAdapters are also removed, and lifecycle of activities (using fragments) has been streamlined.
This commit is contained in:
committed by
daniele
parent
23210bac26
commit
b0d76f8204
-68
@@ -1,68 +0,0 @@
|
||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer, Daniele Gobbetti
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
public abstract class AbstractFragmentPagerAdapter extends FragmentStatePagerAdapter {
|
||||
private final Set<AbstractGBFragment> fragments = new HashSet<>();
|
||||
private Object primaryFragment;
|
||||
|
||||
public AbstractFragmentPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
Object fragment = super.instantiateItem(container, position);
|
||||
if (fragment instanceof AbstractGBFragment) {
|
||||
fragments.add((AbstractGBFragment) fragment);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
super.destroyItem(container, position, object);
|
||||
fragments.remove(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
super.setPrimaryItem(container, position, object);
|
||||
if (object != primaryFragment) {
|
||||
primaryFragment = object;
|
||||
setCurrentFragment(primaryFragment);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCurrentFragment(Object newCurrentFragment) {
|
||||
for (AbstractGBFragment frag : fragments) {
|
||||
if (frag != newCurrentFragment) {
|
||||
frag.onMadeInvisibleInActivity();
|
||||
} else {
|
||||
frag.onMadeVisibleInActivityInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-44
@@ -21,54 +21,11 @@ import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
/**
|
||||
* Abstract base class for fragments. Provides hooks that are called when
|
||||
* the fragment is made visible and invisible in the activity. also allows
|
||||
* Abstract base class for fragments. Allows
|
||||
* the fragment to define the title to be shown in the activity.
|
||||
*
|
||||
* @see AbstractGBFragmentActivity
|
||||
*/
|
||||
public abstract class AbstractGBFragment extends Fragment {
|
||||
private boolean mVisibleInActivity;
|
||||
|
||||
/**
|
||||
* Called when this fragment has been fully scrolled into the activity.
|
||||
*
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeInvisibleInActivity()
|
||||
*/
|
||||
protected void onMadeVisibleInActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this fragment has been scrolled out of the activity.
|
||||
*
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeVisibleInActivity()
|
||||
*/
|
||||
public void onMadeInvisibleInActivity() {
|
||||
mVisibleInActivity = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this fragment is currently visible in the hosting
|
||||
* activity, not taking into account whether the screen is enabled at all.
|
||||
*/
|
||||
public boolean isVisibleInActivity() {
|
||||
return mVisibleInActivity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract CharSequence getTitle();
|
||||
|
||||
/**
|
||||
* Internal
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void onMadeVisibleInActivityInternal() {
|
||||
mVisibleInActivity = true;
|
||||
if (isVisible()) {
|
||||
onMadeVisibleInActivity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
/* Copyright (C) 2015-2024 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
||||
Gobbetti
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
/**
|
||||
* A base activity that supports paging through fragments by swiping.
|
||||
* Subclasses will have to add a ViewPager to their layout and add something
|
||||
* like this to hook it to the fragments:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* // Set up the ViewPager with the sections adapter.
|
||||
* ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
|
||||
* viewPager.setAdapter(getPagerAdapter());
|
||||
* </pre>
|
||||
*
|
||||
* @see AbstractGBFragment
|
||||
*/
|
||||
public abstract class AbstractGBFragmentActivity extends AbstractGBActivity {
|
||||
/**
|
||||
* The {@link PagerAdapter} that will provide
|
||||
* fragments for each of the sections. We use a
|
||||
* {@link FragmentPagerAdapter} derivative, which will keep every
|
||||
* loaded fragment in memory. If this becomes too memory intensive, it
|
||||
* may be best to switch to a
|
||||
* {@link FragmentStatePagerAdapter}.
|
||||
*/
|
||||
private AbstractFragmentPagerAdapter mSectionsPagerAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Create the adapter that will return a fragment for each of the three
|
||||
// primary sections of the activity.
|
||||
mSectionsPagerAdapter = createFragmentPagerAdapter(getSupportFragmentManager());
|
||||
}
|
||||
|
||||
public AbstractFragmentPagerAdapter getPagerAdapter() {
|
||||
return mSectionsPagerAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PagerAdapter that will create the fragments to be used with this
|
||||
* activity. The fragments should typically extend AbstractGBFragment
|
||||
*
|
||||
* @param fragmentManager
|
||||
* @return
|
||||
*/
|
||||
protected abstract AbstractFragmentPagerAdapter createFragmentPagerAdapter(FragmentManager fragmentManager);
|
||||
}
|
||||
+27
-27
@@ -26,6 +26,8 @@ import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -42,11 +44,11 @@ import java.util.UUID;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NavUtils;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractFragmentPagerAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragmentActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
@@ -54,7 +56,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
|
||||
public class AppManagerActivity extends AbstractGBFragmentActivity {
|
||||
public class AppManagerActivity extends AbstractGBActivity {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AppManagerActivity.class);
|
||||
private static final int READ_REQUEST_CODE = 42;
|
||||
@@ -109,15 +111,16 @@ public class AppManagerActivity extends AbstractGBFragmentActivity {
|
||||
}
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
ViewPager viewPager = findViewById(R.id.appmanager_pager);
|
||||
ViewPager2 viewPager = findViewById(R.id.appmanager_pager);
|
||||
if (viewPager != null) {
|
||||
viewPager.setAdapter(getPagerAdapter());
|
||||
viewPager.setAdapter(new SectionsStateAdapter(this));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractFragmentPagerAdapter createFragmentPagerAdapter(FragmentManager fragmentManager) {
|
||||
return new SectionsPagerAdapter(fragmentManager);
|
||||
TabLayout tabLayout = findViewById(R.id.charts_pagerTabStrip);
|
||||
new TabLayoutMediator(tabLayout, viewPager,
|
||||
(tab, position) -> {
|
||||
tab.setText(getPageTitle(position));
|
||||
}).attach();
|
||||
}
|
||||
|
||||
public static synchronized void deleteFromAppOrderFile(String filename, UUID uuid) {
|
||||
@@ -126,16 +129,14 @@ public class AppManagerActivity extends AbstractGBFragmentActivity {
|
||||
rewriteAppOrderFile(filename, uuids);
|
||||
}
|
||||
|
||||
public class SectionsPagerAdapter extends AbstractFragmentPagerAdapter {
|
||||
|
||||
SectionsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
public class SectionsStateAdapter extends FragmentStateAdapter {
|
||||
SectionsStateAdapter(FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
// getItem is called to instantiate the fragment for the given page.
|
||||
public Fragment createFragment(int position) {
|
||||
return switch (enabledTabsList.get(position)) {
|
||||
case "cache" -> new AppManagerFragmentCache();
|
||||
case "apps" -> new AppManagerFragmentInstalledApps();
|
||||
@@ -145,19 +146,18 @@ public class AppManagerActivity extends AbstractGBFragmentActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
public int getItemCount() {
|
||||
return enabledTabsList.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return switch (enabledTabsList.get(position)) {
|
||||
case "cache" -> getString(R.string.appmanager_cached_watchapps_watchfaces);
|
||||
case "apps" -> getString(R.string.appmanager_installed_watchapps);
|
||||
case "watchfaces" -> getString(R.string.appmanager_installed_watchfaces);
|
||||
default -> super.getPageTitle(position);
|
||||
};
|
||||
}
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return switch (enabledTabsList.get(position)) {
|
||||
case "cache" -> getString(R.string.appmanager_cached_watchapps_watchfaces);
|
||||
case "apps" -> getString(R.string.appmanager_installed_watchapps);
|
||||
case "watchfaces" -> getString(R.string.appmanager_installed_watchfaces);
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-10
@@ -147,17 +147,17 @@ public abstract class AbstractChartFragment<D extends ChartsData> extends Abstra
|
||||
/**
|
||||
* Called when this fragment has been fully scrolled into the activity.
|
||||
*
|
||||
* @see #isVisibleInActivity()
|
||||
* @see #onMadeInvisibleInActivity()
|
||||
*/
|
||||
@Override
|
||||
protected void onMadeVisibleInActivity() {
|
||||
super.onMadeVisibleInActivity();
|
||||
showDateBar(true);
|
||||
updateDateInfo(getStartDate(), getEndDate());
|
||||
if (mChartDirty) {
|
||||
refresh();
|
||||
public void onResume() {
|
||||
if ((requireActivity() instanceof ChartsHost)) {
|
||||
showDateBar(true);
|
||||
updateDateInfo(getStartDate(), getEndDate());
|
||||
if (mChartDirty) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
protected ChartsHost getChartsHost() {
|
||||
@@ -248,7 +248,7 @@ public abstract class AbstractChartFragment<D extends ChartsData> extends Abstra
|
||||
* @param offset the offset, in days
|
||||
*/
|
||||
private void handleDate(Date startDate, Date endDate, Integer offset) {
|
||||
if (isVisibleInActivity()) {
|
||||
if (isResumed()) {
|
||||
if (!shiftDates(startDate, endDate, offset)) {
|
||||
return;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ public abstract class AbstractChartFragment<D extends ChartsData> extends Abstra
|
||||
}
|
||||
|
||||
private void refreshIfVisible() {
|
||||
if (isVisibleInActivity()) {
|
||||
if (isResumed()) {
|
||||
refresh();
|
||||
} else {
|
||||
mChartDirty = true;
|
||||
|
||||
-360
@@ -1,360 +0,0 @@
|
||||
/* Copyright (C) 2023-2024 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragmentActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
public abstract class AbstractChartsActivity extends AbstractGBFragmentActivity implements ChartsHost {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractChartsActivity.class);
|
||||
|
||||
public static final String STATE_START_DATE = "stateStartDate";
|
||||
public static final String STATE_END_DATE = "stateEndDate";
|
||||
|
||||
public static final String EXTRA_FRAGMENT_ID = "fragmentId";
|
||||
public static final String EXTRA_SINGLE_FRAGMENT_NAME = "singleFragmentName";
|
||||
public static final String EXTRA_ACTIONBAR_TITLE = "actionbarTitle";
|
||||
public static final String EXTRA_TIMESTAMP = "timestamp";
|
||||
public static final String EXTRA_MODE = "mode";
|
||||
|
||||
private TextView mDateControl;
|
||||
|
||||
private Date mStartDate;
|
||||
private Date mEndDate;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
|
||||
List<String> enabledTabsList;
|
||||
|
||||
private GBDevice mGBDevice;
|
||||
private ViewGroup dateBar;
|
||||
|
||||
private ActivityResultLauncher<Intent> chartsPreferencesLauncher;
|
||||
private final ActivityResultCallback<ActivityResult> chartsPreferencesCallback = result -> {
|
||||
recreate();
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (Objects.requireNonNull(action)) {
|
||||
case GBDevice.ACTION_DEVICE_CHANGED:
|
||||
final GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
|
||||
if (dev != null) {
|
||||
refreshBusyState(dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void refreshBusyState(final GBDevice dev) {
|
||||
if (dev.isBusy()) {
|
||||
swipeLayout.setRefreshing(true);
|
||||
} else {
|
||||
final boolean wasBusy = swipeLayout.isRefreshing();
|
||||
swipeLayout.setRefreshing(false);
|
||||
if (wasBusy) {
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(REFRESH));
|
||||
}
|
||||
}
|
||||
enableSwipeRefresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_charts);
|
||||
|
||||
final Bundle extras = getIntent().getExtras();
|
||||
if (extras == null) {
|
||||
throw new IllegalArgumentException("Must provide a device when invoking this activity");
|
||||
}
|
||||
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
|
||||
chartsPreferencesLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
chartsPreferencesCallback
|
||||
);
|
||||
|
||||
// Set start and end date
|
||||
if (savedInstanceState != null) {
|
||||
setEndDate(new Date(savedInstanceState.getLong(STATE_END_DATE, System.currentTimeMillis())));
|
||||
} else if (extras.containsKey(EXTRA_TIMESTAMP)) {
|
||||
final int endTimestamp = extras.getInt(EXTRA_TIMESTAMP, 0);
|
||||
setEndDate(new Date(endTimestamp * 1000L));
|
||||
} else {
|
||||
setEndDate(new Date());
|
||||
}
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
|
||||
final IntentFilter filterLocal = new IntentFilter();
|
||||
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
|
||||
|
||||
// Open the specified fragment, if any, and setup single page view if specified
|
||||
final int tabFragmentIdToOpen = extras.getInt(EXTRA_FRAGMENT_ID, -1);
|
||||
final String singleFragmentName = extras.getString(EXTRA_SINGLE_FRAGMENT_NAME, null);
|
||||
final int actionbarTitle = extras.getInt(EXTRA_ACTIONBAR_TITLE, 0);
|
||||
|
||||
if (tabFragmentIdToOpen >= 0 && singleFragmentName != null) {
|
||||
throw new IllegalArgumentException("Must specify either fragment ID or single fragment name, not both");
|
||||
}
|
||||
|
||||
if (singleFragmentName != null) {
|
||||
enabledTabsList = Collections.singletonList(singleFragmentName);
|
||||
} else {
|
||||
enabledTabsList = fillChartsTabsList();
|
||||
}
|
||||
|
||||
swipeLayout = findViewById(R.id.activity_swipe_layout);
|
||||
swipeLayout.setOnRefreshListener(this::fetchRecordedData);
|
||||
enableSwipeRefresh(true);
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
final NonSwipeableViewPager viewPager = findViewById(R.id.charts_pager);
|
||||
viewPager.setAdapter(getPagerAdapter());
|
||||
if (tabFragmentIdToOpen > -1) {
|
||||
viewPager.setCurrentItem(tabFragmentIdToOpen); // open the tab as specified in the intent
|
||||
}
|
||||
|
||||
viewPager.setAllowSwipe(singleFragmentName == null && GBApplication.getPrefs().getBoolean("charts_allow_swipe", true));
|
||||
|
||||
if (singleFragmentName != null) {
|
||||
final TabLayout tabLayout = findViewById(R.id.charts_pagerTabStrip);
|
||||
tabLayout.setVisibility(TextView.GONE);
|
||||
}
|
||||
|
||||
if (actionbarTitle != 0) {
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(actionbarTitle);
|
||||
}
|
||||
}
|
||||
|
||||
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
enableSwipeRefresh(state == ViewPager.SCROLL_STATE_IDLE);
|
||||
}
|
||||
});
|
||||
|
||||
dateBar = findViewById(R.id.charts_date_bar);
|
||||
mDateControl = findViewById(R.id.charts_text_date);
|
||||
mDateControl.setOnClickListener(v -> {
|
||||
String detailedDuration = formatDetailedDuration();
|
||||
new ShowDurationDialog(detailedDuration, AbstractChartsActivity.this).show();
|
||||
});
|
||||
|
||||
final Button mPrevButton = findViewById(R.id.charts_previous_day);
|
||||
mPrevButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_DAY));
|
||||
final Button mNextButton = findViewById(R.id.charts_next_day);
|
||||
mNextButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_DAY));
|
||||
|
||||
final Button mPrevWeekButton = findViewById(R.id.charts_previous_week);
|
||||
mPrevWeekButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_WEEK));
|
||||
final Button mNextWeekButton = findViewById(R.id.charts_next_week);
|
||||
mNextWeekButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_WEEK));
|
||||
|
||||
final Button mPrevMonthButton = findViewById(R.id.charts_previous_month);
|
||||
mPrevMonthButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_MONTH));
|
||||
final Button mNextMonthButton = findViewById(R.id.charts_next_month);
|
||||
mNextMonthButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_MONTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putLong(STATE_END_DATE, getEndDate().getTime());
|
||||
outState.putLong(STATE_START_DATE, getStartDate().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
setEndDate(new Date(savedInstanceState.getLong(STATE_END_DATE, System.currentTimeMillis())));
|
||||
setStartDate(new Date(savedInstanceState.getLong(STATE_START_DATE, DateTimeUtils.shiftByDays(getEndDate(), -1).getTime())));
|
||||
}
|
||||
|
||||
protected abstract List<String> fillChartsTabsList();
|
||||
|
||||
private String formatDetailedDuration() {
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
|
||||
final String dateStringFrom = dateFormat.format(getStartDate());
|
||||
final String dateStringTo = dateFormat.format(getEndDate());
|
||||
|
||||
return getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo);
|
||||
}
|
||||
|
||||
protected void initDates() {
|
||||
setEndDate(new Date());
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDevice getDevice() {
|
||||
return mGBDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartDate(Date startDate) {
|
||||
mStartDate = startDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEndDate(Date endDate) {
|
||||
mEndDate = endDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return mStartDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return mEndDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateInfo(final String dateInfo) {
|
||||
mDateControl.setText(dateInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup getDateBar() {
|
||||
return dateBar;
|
||||
}
|
||||
|
||||
private void handleButtonClicked(final String action) {
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(action));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.menu_charts, menu);
|
||||
|
||||
if (!mGBDevice.isConnected() || !supportsRefresh()) {
|
||||
menu.removeItem(R.id.charts_fetch_activity_data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
final int itemId = item.getItemId();
|
||||
if (itemId == R.id.charts_fetch_activity_data) {
|
||||
fetchRecordedData();
|
||||
return true;
|
||||
} else if (itemId == R.id.charts_set_date) {
|
||||
final Calendar currentDate = Calendar.getInstance();
|
||||
currentDate.setTime(getEndDate());
|
||||
new DatePickerDialog(this, (view, year, monthOfYear, dayOfMonth) -> {
|
||||
currentDate.set(year, monthOfYear, dayOfMonth);
|
||||
setEndDate(currentDate.getTime());
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(REFRESH));
|
||||
}, currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE)).show();
|
||||
} else if (itemId == R.id.prefs_charts_menu) {
|
||||
final Intent settingsIntent = new Intent(this, ChartsPreferencesActivity.class);
|
||||
chartsPreferencesLauncher.launch(settingsIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableSwipeRefresh(final boolean enable) {
|
||||
swipeLayout.setEnabled(enable && GBApplication.getPrefs().refreshOnSwipe() && allowRefresh());
|
||||
}
|
||||
|
||||
protected abstract boolean supportsRefresh();
|
||||
|
||||
protected abstract boolean allowRefresh();
|
||||
|
||||
protected abstract int getRecordedDataType();
|
||||
|
||||
private void fetchRecordedData() {
|
||||
if (getDevice().isInitialized()) {
|
||||
GBApplication.deviceService(getDevice()).onFetchRecordedData(getRecordedDataType());
|
||||
} else {
|
||||
swipeLayout.setRefreshing(false);
|
||||
GB.toast(this, getString(R.string.device_not_connected), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-37
@@ -23,7 +23,7 @@ import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@@ -31,18 +31,14 @@ import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
|
||||
public abstract class AbstractCollectionFragment extends AbstractGBFragment {
|
||||
protected static final String ARG_ALLOW_SWIPE = "allow_swipe";
|
||||
|
||||
protected NestedFragmentAdapter nestedFragmentsAdapter;
|
||||
protected FragmentStateAdapter fragmentAdapter;
|
||||
protected ViewPager2 viewPager;
|
||||
private int last_position = 0;
|
||||
private boolean allowSwipe;
|
||||
|
||||
public abstract NestedFragmentAdapter getNestedFragmentAdapter(final AbstractGBFragment fragment,
|
||||
final FragmentManager childFragmentManager);
|
||||
public abstract FragmentStateAdapter getFragmentAdapter();
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
@@ -52,44 +48,18 @@ public abstract class AbstractCollectionFragment extends AbstractGBFragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMadeVisibleInActivity() {
|
||||
super.onMadeVisibleInActivity();
|
||||
nestedFragmentsAdapter.updateFragments(last_position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMadeInvisibleInActivity() {
|
||||
if (nestedFragmentsAdapter != null) {
|
||||
nestedFragmentsAdapter.updateFragments(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_nested_tabs, container, false);
|
||||
nestedFragmentsAdapter = getNestedFragmentAdapter(this, getChildFragmentManager());
|
||||
|
||||
fragmentAdapter = getFragmentAdapter();
|
||||
viewPager = rootView.findViewById(R.id.pager);
|
||||
viewPager.setAdapter(nestedFragmentsAdapter);
|
||||
viewPager.setAdapter(fragmentAdapter);
|
||||
|
||||
if (!allowSwipe) {
|
||||
viewPager.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
|
||||
viewPager.setUserInputEnabled(false);
|
||||
}
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
last_position = position;
|
||||
viewPager.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isVisibleInActivity()) {
|
||||
nestedFragmentsAdapter.updateFragments(position);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
+372
-67
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2023-2024 Daniel Dakhno, José Rebelo, Martin.JM
|
||||
/* Copyright (C) 2023-2024 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@@ -16,61 +16,246 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractFragmentPagerAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
public class ActivityChartsActivity extends AbstractGBActivity implements ChartsHost {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActivityChartsActivity.class);
|
||||
|
||||
public static final String STATE_START_DATE = "stateStartDate";
|
||||
public static final String STATE_END_DATE = "stateEndDate";
|
||||
|
||||
public static final String EXTRA_FRAGMENT_ID = "fragmentId";
|
||||
public static final String EXTRA_SINGLE_FRAGMENT_NAME = "singleFragmentName";
|
||||
public static final String EXTRA_ACTIONBAR_TITLE = "actionbarTitle";
|
||||
public static final String EXTRA_TIMESTAMP = "timestamp";
|
||||
public static final String EXTRA_MODE = "mode";
|
||||
|
||||
private TextView mDateControl;
|
||||
|
||||
private Date mStartDate;
|
||||
private Date mEndDate;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
LimitedQueue<Integer, ActivityAmounts> mActivityAmountCache = new LimitedQueue<>(60);
|
||||
|
||||
@Override
|
||||
protected AbstractFragmentPagerAdapter createFragmentPagerAdapter(final FragmentManager fragmentManager) {
|
||||
return new SectionsPagerAdapter(fragmentManager);
|
||||
List<String> enabledTabsList;
|
||||
|
||||
private GBDevice mGBDevice;
|
||||
private ViewGroup dateBar;
|
||||
|
||||
private ActivityResultLauncher<Intent> chartsPreferencesLauncher;
|
||||
private final ActivityResultCallback<ActivityResult> chartsPreferencesCallback = result -> {
|
||||
recreate();
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
//noinspection SwitchStatementWithTooFewBranches
|
||||
switch (Objects.requireNonNull(action)) {
|
||||
case GBDevice.ACTION_DEVICE_CHANGED:
|
||||
final GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
|
||||
if (dev != null) {
|
||||
refreshBusyState(dev);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void refreshBusyState(final GBDevice dev) {
|
||||
if (dev.isBusy()) {
|
||||
swipeLayout.setRefreshing(true);
|
||||
} else {
|
||||
final boolean wasBusy = swipeLayout.isRefreshing();
|
||||
swipeLayout.setRefreshing(false);
|
||||
if (wasBusy) {
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(REFRESH));
|
||||
}
|
||||
}
|
||||
enableSwipeRefresh(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRecordedDataType() {
|
||||
return RecordedDataTypes.TYPE_ACTIVITY | RecordedDataTypes.TYPE_STRESS;
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_charts);
|
||||
|
||||
final Bundle extras = getIntent().getExtras();
|
||||
if (extras == null) {
|
||||
throw new IllegalArgumentException("Must provide a device when invoking this activity");
|
||||
}
|
||||
|
||||
mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE);
|
||||
|
||||
chartsPreferencesLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
chartsPreferencesCallback
|
||||
);
|
||||
|
||||
// Set start and end date
|
||||
if (savedInstanceState != null) {
|
||||
setEndDate(new Date(savedInstanceState.getLong(STATE_END_DATE, System.currentTimeMillis())));
|
||||
} else if (extras.containsKey(EXTRA_TIMESTAMP)) {
|
||||
final int endTimestamp = extras.getInt(EXTRA_TIMESTAMP, 0);
|
||||
setEndDate(new Date(endTimestamp * 1000L));
|
||||
} else {
|
||||
setEndDate(new Date());
|
||||
}
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
|
||||
final IntentFilter filterLocal = new IntentFilter();
|
||||
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
|
||||
|
||||
// Open the specified fragment, if any, and setup single page view if specified
|
||||
final int tabFragmentIdToOpen = extras.getInt(EXTRA_FRAGMENT_ID, -1);
|
||||
final String singleFragmentName = extras.getString(EXTRA_SINGLE_FRAGMENT_NAME, null);
|
||||
final int actionbarTitle = extras.getInt(EXTRA_ACTIONBAR_TITLE, 0);
|
||||
|
||||
if (tabFragmentIdToOpen >= 0 && singleFragmentName != null) {
|
||||
throw new IllegalArgumentException("Must specify either fragment ID or single fragment name, not both");
|
||||
}
|
||||
|
||||
if (singleFragmentName != null) {
|
||||
enabledTabsList = Collections.singletonList(singleFragmentName);
|
||||
} else {
|
||||
enabledTabsList = fillChartsTabsList();
|
||||
}
|
||||
|
||||
swipeLayout = findViewById(R.id.activity_swipe_layout);
|
||||
swipeLayout.setOnRefreshListener(this::fetchRecordedData);
|
||||
enableSwipeRefresh(true);
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
final ViewPager2 viewPager = findViewById(R.id.charts_pager);
|
||||
TabLayout tabLayout = findViewById(R.id.charts_pagerTabStrip);
|
||||
|
||||
viewPager.setAdapter(getPagerAdapter());
|
||||
|
||||
new TabLayoutMediator(tabLayout, viewPager,
|
||||
(tab, position) -> {
|
||||
tab.setText(getPageTitle(position));
|
||||
}).attach();
|
||||
|
||||
if (tabFragmentIdToOpen > -1) {
|
||||
viewPager.setCurrentItem(tabFragmentIdToOpen); // open the tab as specified in the intent
|
||||
}
|
||||
|
||||
viewPager.setUserInputEnabled(singleFragmentName == null && GBApplication.getPrefs().getBoolean("charts_allow_swipe", true));
|
||||
|
||||
if (singleFragmentName != null) {
|
||||
tabLayout.setVisibility(TextView.GONE);
|
||||
}
|
||||
|
||||
if (actionbarTitle != 0) {
|
||||
final ActionBar actionBar = getSupportActionBar();
|
||||
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(actionbarTitle);
|
||||
}
|
||||
}
|
||||
|
||||
dateBar = findViewById(R.id.charts_date_bar);
|
||||
mDateControl = findViewById(R.id.charts_text_date);
|
||||
mDateControl.setOnClickListener(v -> {
|
||||
String detailedDuration = formatDetailedDuration();
|
||||
new ShowDurationDialog(detailedDuration, ActivityChartsActivity.this).show();
|
||||
});
|
||||
|
||||
final Button mPrevButton = findViewById(R.id.charts_previous_day);
|
||||
mPrevButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_DAY));
|
||||
final Button mNextButton = findViewById(R.id.charts_next_day);
|
||||
mNextButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_DAY));
|
||||
|
||||
final Button mPrevWeekButton = findViewById(R.id.charts_previous_week);
|
||||
mPrevWeekButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_WEEK));
|
||||
final Button mNextWeekButton = findViewById(R.id.charts_next_week);
|
||||
mNextWeekButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_WEEK));
|
||||
|
||||
final Button mPrevMonthButton = findViewById(R.id.charts_previous_month);
|
||||
mPrevMonthButton.setOnClickListener(v -> handleButtonClicked(DATE_PREV_MONTH));
|
||||
final Button mNextMonthButton = findViewById(R.id.charts_next_month);
|
||||
mNextMonthButton.setOnClickListener(v -> handleButtonClicked(DATE_NEXT_MONTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRefresh() {
|
||||
final DeviceCoordinator coordinator = getDevice().getDeviceCoordinator();
|
||||
return coordinator.supportsActivityDataFetching(getDevice());
|
||||
protected void onSaveInstanceState(@NonNull final Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putLong(STATE_END_DATE, getEndDate().getTime());
|
||||
outState.putLong(STATE_START_DATE, getStartDate().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowRefresh() {
|
||||
final DeviceCoordinator coordinator = getDevice().getDeviceCoordinator();
|
||||
return coordinator.allowFetchActivityData(getDevice()) && supportsRefresh();
|
||||
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
setEndDate(new Date(savedInstanceState.getLong(STATE_END_DATE, System.currentTimeMillis())));
|
||||
setStartDate(new Date(savedInstanceState.getLong(STATE_START_DATE, DateTimeUtils.shiftByDays(getEndDate(), -1).getTime())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FragmentStateAdapter getPagerAdapter() {
|
||||
return new SectionsStateAdapter(this);
|
||||
}
|
||||
protected List<String> fillChartsTabsList() {
|
||||
return fillChartsTabsList(getDevice(), this);
|
||||
}
|
||||
@@ -150,18 +335,183 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
return enabledTabsList.indexOf(tab);
|
||||
}
|
||||
|
||||
private String formatDetailedDuration() {
|
||||
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
|
||||
final String dateStringFrom = dateFormat.format(getStartDate());
|
||||
final String dateStringTo = dateFormat.format(getEndDate());
|
||||
|
||||
return getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo);
|
||||
}
|
||||
|
||||
protected void initDates() {
|
||||
setEndDate(new Date());
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDevice getDevice() {
|
||||
return mGBDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartDate(Date startDate) {
|
||||
mStartDate = startDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEndDate(Date endDate) {
|
||||
mEndDate = endDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return mStartDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return mEndDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateInfo(final String dateInfo) {
|
||||
mDateControl.setText(dateInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup getDateBar() {
|
||||
return dateBar;
|
||||
}
|
||||
|
||||
private void handleButtonClicked(final String action) {
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(action));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.menu_charts, menu);
|
||||
|
||||
if (!mGBDevice.isConnected() || !supportsRefresh()) {
|
||||
menu.removeItem(R.id.charts_fetch_activity_data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
final int itemId = item.getItemId();
|
||||
if (itemId == R.id.charts_fetch_activity_data) {
|
||||
fetchRecordedData();
|
||||
return true;
|
||||
} else if (itemId == R.id.charts_set_date) {
|
||||
final Calendar currentDate = Calendar.getInstance();
|
||||
currentDate.setTime(getEndDate());
|
||||
new DatePickerDialog(this, (view, year, monthOfYear, dayOfMonth) -> {
|
||||
currentDate.set(year, monthOfYear, dayOfMonth);
|
||||
setEndDate(currentDate.getTime());
|
||||
setStartDate(DateTimeUtils.shiftByDays(getEndDate(), -1));
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(REFRESH));
|
||||
}, currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE)).show();
|
||||
} else if (itemId == R.id.prefs_charts_menu) {
|
||||
final Intent settingsIntent = new Intent(this, ChartsPreferencesActivity.class);
|
||||
chartsPreferencesLauncher.launch(settingsIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableSwipeRefresh(final boolean enable) {
|
||||
swipeLayout.setEnabled(enable && allowRefresh());
|
||||
}
|
||||
|
||||
protected boolean supportsRefresh() {
|
||||
final DeviceCoordinator coordinator = getDevice().getDeviceCoordinator();
|
||||
return coordinator.supportsActivityDataFetching(getDevice());
|
||||
}
|
||||
|
||||
protected boolean allowRefresh() {
|
||||
final DeviceCoordinator coordinator = getDevice().getDeviceCoordinator();
|
||||
return coordinator.allowFetchActivityData(getDevice()) && supportsRefresh();
|
||||
}
|
||||
|
||||
protected int getRecordedDataType() {
|
||||
return RecordedDataTypes.TYPE_ACTIVITY | RecordedDataTypes.TYPE_STRESS;
|
||||
}
|
||||
private void fetchRecordedData() {
|
||||
if (getDevice().isInitialized()) {
|
||||
GBApplication.deviceService(getDevice()).onFetchRecordedData(getRecordedDataType());
|
||||
} else {
|
||||
swipeLayout.setRefreshing(false);
|
||||
GB.toast(this, getString(R.string.device_not_connected), Toast.LENGTH_SHORT, GB.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (enabledTabsList.get(position)) {
|
||||
case "activity":
|
||||
return getString(R.string.activity_sleepchart_activity_and_sleep);
|
||||
case "activitylist":
|
||||
return getString(R.string.charts_activity_list);
|
||||
case "sleep":
|
||||
return getString(R.string.sleepchart_your_sleep);
|
||||
case "heartrate":
|
||||
return getString(R.string.menuitem_hr);
|
||||
case "hrvstatus":
|
||||
return getString(R.string.pref_header_hrv_status);
|
||||
case "bodyenergy":
|
||||
return getString(R.string.body_energy);
|
||||
case "vo2max":
|
||||
return getString(R.string.menuitem_vo2_max);
|
||||
case "stress":
|
||||
return getString(R.string.menuitem_stress);
|
||||
case "pai":
|
||||
return getString(getDevice().getDeviceCoordinator().getPaiName());
|
||||
case "stepsweek":
|
||||
return getString(R.string.steps);
|
||||
case "speedzones":
|
||||
return getString(R.string.stats_title);
|
||||
case "livestats":
|
||||
return getString(R.string.liveactivity_live_activity);
|
||||
case "spo2":
|
||||
return getString(R.string.pref_header_spo2);
|
||||
case "temperature":
|
||||
return getString(R.string.menuitem_temperature);
|
||||
case "cycling":
|
||||
return getString(R.string.title_cycling);
|
||||
case "weight":
|
||||
return getString(R.string.menuitem_weight);
|
||||
case "calories":
|
||||
return getString(R.string.calories);
|
||||
case "respiratoryrate":
|
||||
return getString(R.string.respiratoryrate);
|
||||
case "load":
|
||||
return getString(R.string.pref_header_training_load);
|
||||
}
|
||||
|
||||
return String.format(Locale.getDefault(), "Unknown %d", position);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link FragmentStatePagerAdapter} that returns a fragment corresponding to
|
||||
* one of the sections/tabs/pages.
|
||||
*/
|
||||
private class SectionsPagerAdapter extends AbstractFragmentPagerAdapter {
|
||||
SectionsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
private class SectionsStateAdapter extends FragmentStateAdapter {
|
||||
SectionsStateAdapter(FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
public Fragment createFragment(int position) {
|
||||
final DeviceCoordinator coordinator = getDevice().getDeviceCoordinator();
|
||||
// getItem is called to instantiate the fragment for the given page.
|
||||
switch (enabledTabsList.get(position)) {
|
||||
@@ -205,59 +555,14 @@ public class ActivityChartsActivity extends AbstractChartsActivity {
|
||||
return RespiratoryRateCollectionFragment.newInstance(enabledTabsList.size() == 1);
|
||||
}
|
||||
|
||||
return new UnknownFragment();
|
||||
return new ActivityChartsActivity.UnknownFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
public int getItemCount() {
|
||||
return enabledTabsList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (enabledTabsList.get(position)) {
|
||||
case "activity":
|
||||
return getString(R.string.activity_sleepchart_activity_and_sleep);
|
||||
case "activitylist":
|
||||
return getString(R.string.charts_activity_list);
|
||||
case "sleep":
|
||||
return getString(R.string.sleepchart_your_sleep);
|
||||
case "heartrate":
|
||||
return getString(R.string.menuitem_hr);
|
||||
case "hrvstatus":
|
||||
return getString(R.string.pref_header_hrv_status);
|
||||
case "bodyenergy":
|
||||
return getString(R.string.body_energy);
|
||||
case "vo2max":
|
||||
return getString(R.string.menuitem_vo2_max);
|
||||
case "stress":
|
||||
return getString(R.string.menuitem_stress);
|
||||
case "pai":
|
||||
return getString(getDevice().getDeviceCoordinator().getPaiName());
|
||||
case "stepsweek":
|
||||
return getString(R.string.steps);
|
||||
case "speedzones":
|
||||
return getString(R.string.stats_title);
|
||||
case "livestats":
|
||||
return getString(R.string.liveactivity_live_activity);
|
||||
case "spo2":
|
||||
return getString(R.string.pref_header_spo2);
|
||||
case "temperature":
|
||||
return getString(R.string.menuitem_temperature);
|
||||
case "cycling":
|
||||
return getString(R.string.title_cycling);
|
||||
case "weight":
|
||||
return getString(R.string.menuitem_weight);
|
||||
case "calories":
|
||||
return getString(R.string.calories);
|
||||
case "respiratoryrate":
|
||||
return getString(R.string.respiratoryrate);
|
||||
case "load":
|
||||
return getString(R.string.pref_header_training_load);
|
||||
}
|
||||
|
||||
return String.format(Locale.getDefault(), "Unknown %d", position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-5
@@ -18,11 +18,9 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.CaloriesFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
|
||||
public class CaloriesCollectionFragment extends AbstractCollectionFragment {
|
||||
public CaloriesCollectionFragment() {
|
||||
@@ -38,8 +36,8 @@ public class CaloriesCollectionFragment extends AbstractCollectionFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new CaloriesFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new CaloriesFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -18,10 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.HeartRateFragmentAdapter;
|
||||
|
||||
public class HeartRateCollectionFragment extends AbstractCollectionFragment {
|
||||
@@ -38,7 +36,7 @@ public class HeartRateCollectionFragment extends AbstractCollectionFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new HeartRateFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new HeartRateFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -369,12 +369,6 @@ public class LiveActivityFragment extends AbstractActivityChartFragment<ChartsDa
|
||||
GBApplication.deviceService(getChartsHost().getDevice()).onEnableRealtimeHeartRateMeasurement(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMadeVisibleInActivity() {
|
||||
super.onMadeVisibleInActivity();
|
||||
enableRealtimeTracking(true);
|
||||
}
|
||||
|
||||
private void enableRealtimeTracking(boolean enable) {
|
||||
if (enable && pulseScheduler != null) {
|
||||
// already running
|
||||
@@ -403,15 +397,9 @@ public class LiveActivityFragment extends AbstractActivityChartFragment<ChartsDa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMadeInvisibleInActivity() {
|
||||
enableRealtimeTracking(false);
|
||||
super.onMadeInvisibleInActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
onMadeInvisibleInActivity();
|
||||
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mReceiver);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/* Copyright (C) 2023-2024 José Rebelo
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
|
||||
public class NonSwipeableViewPager extends ViewPager {
|
||||
private boolean allowSwipe = true;
|
||||
|
||||
public NonSwipeableViewPager(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void setAllowSwipe(final boolean allowSwipe) {
|
||||
this.allowSwipe = allowSwipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(final MotionEvent ev) {
|
||||
if (allowSwipe) {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent ev) {
|
||||
if (allowSwipe) {
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+3
-5
@@ -2,10 +2,8 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.RespiratoryRateFragmentAdapter;
|
||||
|
||||
public class RespiratoryRateCollectionFragment extends AbstractCollectionFragment {
|
||||
@@ -22,8 +20,8 @@ public class RespiratoryRateCollectionFragment extends AbstractCollectionFragmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new RespiratoryRateFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new RespiratoryRateFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -18,10 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.SleepFragmentAdapter;
|
||||
|
||||
public class SleepCollectionFragment extends AbstractCollectionFragment {
|
||||
@@ -38,7 +36,7 @@ public class SleepCollectionFragment extends AbstractCollectionFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new SleepFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new SleepFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -18,10 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.StepsFragmentAdapter;
|
||||
|
||||
public class StepsCollectionFragment extends AbstractCollectionFragment {
|
||||
@@ -38,8 +36,8 @@ public class StepsCollectionFragment extends AbstractCollectionFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new StepsFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new StepsFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -18,10 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.NestedFragmentAdapter;
|
||||
import nodomain.freeyourgadget.gadgetbridge.adapter.StressFragmentAdapter;
|
||||
|
||||
public class StressCollectionFragment extends AbstractCollectionFragment {
|
||||
@@ -38,7 +36,7 @@ public class StressCollectionFragment extends AbstractCollectionFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedFragmentAdapter getNestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
return new StressFragmentAdapter(this, getChildFragmentManager());
|
||||
public FragmentStateAdapter getFragmentAdapter() {
|
||||
return new StressFragmentAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -9,11 +9,9 @@ import nodomain.freeyourgadget.gadgetbridge.activities.charts.CaloriesDailyFragm
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.CaloriesPeriodFragment;
|
||||
|
||||
public class CaloriesFragmentAdapter extends NestedFragmentAdapter {
|
||||
protected FragmentManager fragmentManager;
|
||||
|
||||
public CaloriesFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
fragmentManager = childFragmentManager;
|
||||
public CaloriesFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+2
-3
@@ -2,14 +2,13 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.HeartRatePeriodFragment;
|
||||
|
||||
public class HeartRateFragmentAdapter extends NestedFragmentAdapter {
|
||||
public HeartRateFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
public HeartRateFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+5
-22
@@ -16,19 +16,13 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
|
||||
public abstract class NestedFragmentAdapter extends FragmentStateAdapter {
|
||||
protected FragmentManager fragmentManager;
|
||||
|
||||
public NestedFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
public NestedFragmentAdapter(@NonNull Fragment fragment) {
|
||||
super(fragment);
|
||||
fragmentManager = childFragmentManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,17 +30,6 @@ public abstract class NestedFragmentAdapter extends FragmentStateAdapter {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public void updateFragments(int position) {
|
||||
List<AbstractGBFragment> fragments = fragmentManager.getFragments()
|
||||
.stream()
|
||||
.map(e -> (AbstractGBFragment) e)
|
||||
.collect(Collectors.toList());
|
||||
for (AbstractGBFragment fragment : fragments) {
|
||||
if (position < 0 || fragment != fragmentManager.findFragmentByTag("f" + position)) {
|
||||
fragment.onMadeInvisibleInActivity();
|
||||
} else {
|
||||
fragment.onMadeVisibleInActivityInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
abstract public Fragment createFragment(int position);
|
||||
}
|
||||
|
||||
+2
-5
@@ -2,18 +2,15 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.RespiratoryRateDailyFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.RespiratoryRatePeriodFragment;
|
||||
|
||||
public class RespiratoryRateFragmentAdapter extends NestedFragmentAdapter {
|
||||
protected FragmentManager fragmentManager;
|
||||
|
||||
public RespiratoryRateFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
fragmentManager = childFragmentManager;
|
||||
public RespiratoryRateFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+2
-3
@@ -2,7 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
@@ -10,8 +9,8 @@ import nodomain.freeyourgadget.gadgetbridge.activities.charts.SleepDailyFragment
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.SleepPeriodFragment;
|
||||
|
||||
public class SleepFragmentAdapter extends NestedFragmentAdapter {
|
||||
public SleepFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
public SleepFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+2
-5
@@ -2,18 +2,15 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractGBFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepsDailyFragment;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepsPeriodFragment;
|
||||
|
||||
public class StepsFragmentAdapter extends NestedFragmentAdapter {
|
||||
protected FragmentManager fragmentManager;
|
||||
|
||||
public StepsFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
fragmentManager = childFragmentManager;
|
||||
public StepsFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@ import nodomain.freeyourgadget.gadgetbridge.activities.charts.StressDailyFragmen
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StressPeriodFragment;
|
||||
|
||||
public class StressFragmentAdapter extends NestedFragmentAdapter {
|
||||
public StressFragmentAdapter(AbstractGBFragment fragment, FragmentManager childFragmentManager) {
|
||||
super(fragment, childFragmentManager);
|
||||
public StressFragmentAdapter(Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<nodomain.freeyourgadget.gadgetbridge.activities.charts.NonSwipeableViewPager
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/charts_pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
app:tabMode="scrollable" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/charts_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ActivityChartsActivity">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/charts_pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
app:tabMode="scrollable" />
|
||||
</nodomain.freeyourgadget.gadgetbridge.activities.charts.NonSwipeableViewPager>
|
||||
</androidx.viewpager2.widget.ViewPager2>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/charts_date_bar"
|
||||
|
||||
@@ -11,18 +11,20 @@
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/charts_pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/appmanager_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activities.appmanager.AppManagerActivity">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/charts_pagerTabStrip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top" />
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
|
||||
</androidx.viewpager2.widget.ViewPager2>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user