Moved Toolbar to individual Fragments

This commit is contained in:
ByteHamster 2020-03-12 13:28:30 +01:00
parent 03d1f41e9b
commit 7f4d43deb1
31 changed files with 967 additions and 844 deletions

View File

@ -1,7 +1,6 @@
package de.danoeh.antennapod.activity;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -11,18 +10,7 @@ import android.database.DataSetObserver;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
@ -31,25 +19,23 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.bumptech.glide.Glide;
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.NavListAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@ -77,6 +63,13 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
/**
* The activity that is shown when the user launches the app.
@ -96,7 +89,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
private static final String EXTRA_FEED_ID = "fragment_feed_id";
private static final String SAVE_BACKSTACK_COUNT = "backstackCount";
private static final String SAVE_TITLE = "title";
public static final String[] NAV_DRAWER_TAGS = {
QueueFragment.TAG,
@ -108,15 +100,11 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
NavListAdapter.SUBSCRIPTION_LIST_TAG
};
private Toolbar toolbar;
private ExternalPlayerFragment externalPlayerFragment;
private DrawerLayout drawerLayout;
private View navDrawer;
private ListView navList;
private NavListAdapter navAdapter;
private int mPosition = -1;
private ActionBarDrawerToggle drawerToggle;
private CharSequence currentTitle;
private Disposable disposable;
private long lastBackButtonPressTime = 0;
@ -135,20 +123,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
StorageUtils.checkStorageAvailability(this);
setContentView(R.layout.main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
findViewById(R.id.shadow).setVisibility(View.GONE);
int elevation = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,
getResources().getDisplayMetrics());
getSupportActionBar().setElevation(elevation);
}
currentTitle = getTitle();
drawerLayout = findViewById(R.id.drawer_layout);
navList = findViewById(R.id.nav_list);
ListView navList = findViewById(R.id.nav_list);
navDrawer = findViewById(R.id.nav_layout);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
@ -162,9 +138,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
fm.addOnBackStackChangedListener(() -> drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
navAdapter = new NavListAdapter(itemAccess, this);
navList.setAdapter(navAdapter);
navList.setOnItemClickListener(navListClickListener);
@ -203,7 +176,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
}
}
externalPlayerFragment = new ExternalPlayerFragment();
ExternalPlayerFragment externalPlayerFragment = new ExternalPlayerFragment();
transaction.replace(R.id.playerFragment, externalPlayerFragment, ExternalPlayerFragment.TAG);
transaction.commit();
@ -315,8 +288,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
args = null;
break;
}
currentTitle = navAdapter.getLabel(tag);
getSupportActionBar().setTitle(currentTitle);
saveLastNavFragment(tag);
if (args != null) {
fragment.setArguments(args);
@ -338,8 +309,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
fragment.setArguments(args);
}
saveLastNavFragment(String.valueOf(feedId));
currentTitle = "";
getSupportActionBar().setTitle(currentTitle);
loadFragment(fragment);
}
@ -452,10 +421,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
if (savedInstanceState != null) {
currentTitle = savedInstanceState.getString(SAVE_TITLE);
if (!drawerLayout.isDrawerOpen(navDrawer)) {
getSupportActionBar().setTitle(currentTitle);
}
selectedNavListIndex = getSelectedNavListIndex();
}
}
@ -469,7 +434,6 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(SAVE_TITLE, getSupportActionBar().getTitle().toString());
outState.putInt(SAVE_BACKSTACK_COUNT, getSupportFragmentManager().getBackStackEntryCount());
}

View File

@ -13,26 +13,17 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.collection.ArrayMap;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.snackbar.Snackbar;
import com.leinardi.android.speeddial.SpeedDialView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.FeedItem;
@ -43,6 +34,12 @@ import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.SortOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class EpisodesApplyActionFragment extends Fragment {
public static final String TAG = "EpisodeActionFragment";
@ -55,6 +52,7 @@ public class EpisodesApplyActionFragment extends Fragment {
public static final int ACTION_DELETE = 32;
private static final int ACTION_ALL = ACTION_ADD_TO_QUEUE | ACTION_REMOVE_FROM_QUEUE
| ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED | ACTION_DOWNLOAD | ACTION_DELETE;
private Toolbar toolbar;
/**
* Specify an action (defined by #flag) 's UI bindings.
@ -76,20 +74,15 @@ public class EpisodesApplyActionFragment extends Fragment {
}
private final List<? extends ActionBinding> actionBindings;
private ListView mListView;
private ArrayAdapter<String> mAdapter;
private SpeedDialView mSpeedDialView;
@NonNull
private CharSequence actionBarTitleOriginal = "";
private final Map<Long,FeedItem> idMap = new ArrayMap<>();
private final Map<Long, FeedItem> idMap = new ArrayMap<>();
private final List<FeedItem> episodes = new ArrayList<>();
private int actions;
private final List<String> titles = new ArrayList<>();
private final LongList checkedIds = new LongList();
private ListView mListView;
private ArrayAdapter<String> mAdapter;
private SpeedDialView mSpeedDialView;
private MenuItem mSelectToggle;
public EpisodesApplyActionFragment() {
@ -137,7 +130,7 @@ public class EpisodesApplyActionFragment extends Fragment {
mListView = view.findViewById(android.R.id.list);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mListView.setOnItemClickListener((ListView, view1, position, rowId) -> {
mListView.setOnItemClickListener((listView, view1, position, rowId) -> {
long id = episodes.get(position).getId();
if (checkedIds.contains(id)) {
checkedIds.remove(id);
@ -177,8 +170,8 @@ public class EpisodesApplyActionFragment extends Fragment {
mAdapter = new ArrayAdapter<>(getActivity(),
R.layout.simple_list_item_multiple_choice_on_start, titles);
mListView.setAdapter(mAdapter);
saveActionBarTitle(); // needed when we dynamically change the title based on selection
toolbar = view.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
// Init action UI (via a FAB Speed Dial)
mSpeedDialView = view.findViewById(R.id.fabSD);
@ -206,18 +199,10 @@ public class EpisodesApplyActionFragment extends Fragment {
}
return true;
});
showSpeedDialIfAnyChecked();
refreshCheckboxes();
return view;
}
@Override
public void onStop() {
restoreActionBarTitle(); // it might have been changed to "N selected". Restore original.
super.onStop();
}
private void showSpeedDialIfAnyChecked() {
if (checkedIds.size() > 0) {
if (!mSpeedDialView.isShown()) {
@ -327,7 +312,7 @@ public class EpisodesApplyActionFragment extends Fragment {
return true;
}
}
if(resId != 0) {
if (resId != 0) {
Snackbar.make(getActivity().findViewById(R.id.content), resId, Snackbar.LENGTH_SHORT)
.show();
return true;
@ -345,7 +330,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkAll() {
for (FeedItem episode : episodes) {
if(!checkedIds.contains(episode.getId())) {
if (!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}
}
@ -359,12 +344,12 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkPlayed(boolean isPlayed) {
for (FeedItem episode : episodes) {
if(episode.isPlayed() == isPlayed) {
if(!checkedIds.contains(episode.getId())) {
if (episode.isPlayed() == isPlayed) {
if (!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}
} else {
if(checkedIds.contains(episode.getId())) {
if (checkedIds.contains(episode.getId())) {
checkedIds.remove(episode.getId());
}
}
@ -374,12 +359,12 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkDownloaded(boolean isDownloaded) {
for (FeedItem episode : episodes) {
if(episode.hasMedia() && episode.getMedia().isDownloaded() == isDownloaded) {
if(!checkedIds.contains(episode.getId())) {
if (episode.hasMedia() && episode.getMedia().isDownloaded() == isDownloaded) {
if (!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}
} else {
if(checkedIds.contains(episode.getId())) {
if (checkedIds.contains(episode.getId())) {
checkedIds.remove(episode.getId());
}
}
@ -389,7 +374,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkQueued(boolean isQueued) {
for (FeedItem episode : episodes) {
if(episode.isTagged(FeedItem.TAG_QUEUE) == isQueued) {
if (episode.isTagged(FeedItem.TAG_QUEUE) == isQueued) {
checkedIds.add(episode.getId());
} else {
checkedIds.remove(episode.getId());
@ -400,7 +385,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkWithMedia() {
for (FeedItem episode : episodes) {
if(episode.hasMedia()) {
if (episode.hasMedia()) {
checkedIds.add(episode.getId());
} else {
checkedIds.remove(episode.getId());
@ -425,35 +410,7 @@ public class EpisodesApplyActionFragment extends Fragment {
}
ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity());
showSpeedDialIfAnyChecked();
updateActionBarTitle();
}
private void saveActionBarTitle() {
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
CharSequence title = actionBar.getTitle();
if (title == null) {
title = "";
}
actionBarTitleOriginal = title;
}
}
private void restoreActionBarTitle() {
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(actionBarTitleOriginal);
}
}
private void updateActionBarTitle() {
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
CharSequence title = checkedIds.size() > 0 ?
getString(R.string.num_selected_label, checkedIds.size()) :
actionBarTitleOriginal;
actionBar.setTitle(title);
}
toolbar.setTitle(getString(R.string.num_selected_label, checkedIds.size()));
}
private void queueChecked() {
@ -487,7 +444,7 @@ public class EpisodesApplyActionFragment extends Fragment {
// download the check episodes in the same order as they are currently displayed
List<FeedItem> toDownload = new ArrayList<>(checkedIds.size());
for (FeedItem episode : episodes) {
if(checkedIds.contains(episode.getId()) && episode.hasMedia()) {
if (checkedIds.contains(episode.getId()) && episode.hasMedia()) {
toDownload.add(episode);
}
}
@ -503,7 +460,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void deleteChecked() {
for (long id : checkedIds.toArray()) {
FeedItem episode = idMap.get(id);
if(episode.hasMedia()) {
if (episode.hasMedia()) {
DBWriter.deleteFeedMediaOfItem(getActivity(), episode.getMedia().getId());
}
}
@ -516,7 +473,7 @@ public class EpisodesApplyActionFragment extends Fragment {
getResources().getQuantityString(msgId, numItems, numItems),
Snackbar.LENGTH_LONG
)
.setAction(android.R.string.ok, v -> {})
.setAction(android.R.string.ok, v -> { })
.show();
}
getActivity().getSupportFragmentManager().popBackStack();

View File

@ -6,6 +6,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@ -41,9 +42,8 @@ public class AddFeedFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.addfeed, container, false);
activity = (MainActivity) getActivity();
activity.getSupportActionBar().setTitle(R.string.add_feed_label);
((AppCompatActivity) getActivity()).setSupportActionBar(root.findViewById(R.id.toolbar));
setupAdvancedSearchButtons(root);
setupSeachBox(root);

View File

@ -4,6 +4,8 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.tabs.TabLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -37,6 +39,9 @@ public class DownloadsFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(R.layout.pager_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.downloads_label);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
viewPager = root.findViewById(R.id.viewpager);
DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources());

View File

@ -2,20 +2,18 @@ package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.google.android.material.tabs.TabLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
public class EpisodesFragment extends Fragment {
@ -38,22 +36,21 @@ public class EpisodesFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
setHasOptionsMenu(true);
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.episodes_label);
View rootView = inflater.inflate(R.layout.pager_fragment, container, false);
Toolbar toolbar = rootView.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.episodes_label);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
viewPager = rootView.findViewById(R.id.viewpager);
viewPager.setAdapter(new EpisodesPagerAdapter());
// Give the TabLayout the ViewPager
tabLayout = rootView.findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
return rootView;
}

View File

@ -8,6 +8,8 @@ import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
@ -22,6 +24,9 @@ import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.snackbar.Snackbar;
import com.joanzapata.iconify.Iconify;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@ -33,8 +38,10 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LangUtils;
import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.view.ToolbarIconTintManager;
import io.reactivex.Maybe;
import io.reactivex.MaybeOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -64,6 +71,8 @@ public class FeedInfoFragment extends Fragment {
private TextView txtvUrl;
private TextView txtvAuthorHeader;
private ImageView imgvBackground;
private Menu optionsMenu;
private ToolbarIconTintManager iconTintManager;
public static FeedInfoFragment newInstance(Feed feed) {
FeedInfoFragment fragment = new FeedInfoFragment();
@ -82,23 +91,33 @@ public class FeedInfoFragment extends Fragment {
android.content.ClipboardManager cm = (android.content.ClipboardManager) getContext()
.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(clipData);
Toast t = Toast.makeText(getContext(), R.string.copied_url_msg, Toast.LENGTH_SHORT);
t.show();
Snackbar.make(getView(), R.string.copied_url_msg, Snackbar.LENGTH_SHORT).show();
}
}
};
@Override
public void onResume() {
super.onResume();
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.feed_info_label);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.feedinfo, null);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle("");
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
AppBarLayout appBar = root.findViewById(R.id.appBar);
CollapsingToolbarLayout collapsingToolbar = root.findViewById(R.id.collapsing_toolbar);
iconTintManager = new ToolbarIconTintManager(getContext(), toolbar, collapsingToolbar) {
@Override
protected void doTint(Context themedContext) {
if (optionsMenu == null) {
return;
}
optionsMenu.findItem(R.id.visit_website_item)
.setIcon(ThemeUtils.getDrawableFromAttr(themedContext, R.attr.location_web_site));
}
};
appBar.addOnOffsetChangedListener(iconTintManager);
setHasOptionsMenu(true);
imgvCover = root.findViewById(R.id.imgvCover);
@ -110,7 +129,6 @@ public class FeedInfoFragment extends Fragment {
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
txtvDescription = root.findViewById(R.id.txtvDescription);
lblLanguage = root.findViewById(R.id.lblLanguage);
txtvLanguage = root.findViewById(R.id.txtvLanguage);
@ -201,6 +219,8 @@ public class FeedInfoFragment extends Fragment {
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.feedinfo, menu);
optionsMenu = menu;
iconTintManager.updateTint();
}
@Override

View File

@ -1,6 +1,5 @@
package de.danoeh.antennapod.fragment;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.LightingColorFilter;
@ -12,31 +11,26 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.ListFragment;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
@ -46,28 +40,23 @@ import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.FeedListUpdateEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedItemFilter;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.glide.FastBlurTransformation;
import de.danoeh.antennapod.core.service.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemPermutors;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.Optional;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
@ -79,12 +68,17 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
/**
* Displays a list of FeedItems.
*/
@SuppressLint("ValidFragment")
public class FeedItemlistFragment extends ListFragment {
public class FeedItemlistFragment extends Fragment implements AdapterView.OnItemClickListener {
private static final String TAG = "ItemlistFragment";
private static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
@ -102,6 +96,8 @@ public class FeedItemlistFragment extends ListFragment {
private ImageView imgvBackground;
private ImageView imgvCover;
private TextView txtvInformation;
private ListView listView;
private ProgressBar progressBar;
private Disposable disposable;
@ -131,22 +127,23 @@ public class FeedItemlistFragment extends ListFragment {
feedID = args.getLong(ARGUMENT_FEED_ID);
}
@Nullable
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden && getActivity() != null) {
((MainActivity) getActivity()).getSupportActionBar().setTitle("");
}
}
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.feed_item_list_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle("");
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
registerForContextMenu(getListView());
listView = root.findViewById(android.R.id.list);
listView.setOnItemClickListener(this);
registerForContextMenu(listView);
progressBar = root.findViewById(R.id.progLoading);
EventBus.getDefault().register(this);
loadItems();
return root;
}
@Override
@ -320,21 +317,20 @@ public class FeedItemlistFragment extends ListFragment {
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
if(adapter == null) {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (adapter == null) {
return;
}
position -= l.getHeaderViewsCount();
position -= listView.getHeaderViewsCount();
MainActivity activity = (MainActivity) getActivity();
long[] ids = FeedItemUtil.getIds(feed.getItems());
activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
activity.getSupportActionBar().setTitle(feed.getTitle());
}
@Subscribe
public void onEvent(FeedEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
if(event.feedId == feedID) {
if (event.feedId == feedID) {
loadItems();
}
}
@ -342,12 +338,12 @@ public class FeedItemlistFragment extends ListFragment {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if(feed == null || feed.getItems() == null || adapter == null) {
if (feed == null || feed.getItems() == null || adapter == null) {
return;
}
for(FeedItem item : event.items) {
for (FeedItem item : event.items) {
int pos = FeedItemUtil.indexOfItemWithId(feed.getItems(), item.getId());
if(pos >= 0) {
if (pos >= 0) {
loadItems();
return;
}
@ -369,7 +365,7 @@ public class FeedItemlistFragment extends ListFragment {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(PlaybackPositionEvent event) {
if (adapter != null) {
adapter.notifyCurrentlyPlayingItemChanged(event, getListView());
adapter.notifyCurrentlyPlayingItemChanged(event, listView);
}
}
@ -412,39 +408,40 @@ public class FeedItemlistFragment extends ListFragment {
return;
}
if (adapter == null) {
setListAdapter(null);
listView.setAdapter(null);
setupHeaderView();
setupFooterView();
adapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, false, true);
setListAdapter(adapter);
listView.setAdapter(adapter);
}
refreshHeaderView();
setListShown(true);
listView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
getActivity().supportInvalidateOptionsMenu();
if (feed != null && feed.getNextPageLink() == null && listFooter != null) {
getListView().removeFooterView(listFooter.getRoot());
listView.removeFooterView(listFooter.getRoot());
}
}
private void refreshHeaderView() {
if (getListView() == null || feed == null || !headerCreated) {
if (listView == null || feed == null || !headerCreated) {
Log.e(TAG, "Unable to refresh header view");
return;
}
loadFeedImage();
if(feed.hasLastUpdateFailed()) {
if (feed.hasLastUpdateFailed()) {
txtvFailure.setVisibility(View.VISIBLE);
} else {
txtvFailure.setVisibility(View.GONE);
}
txtvTitle.setText(feed.getTitle());
if(feed.getItemFilter() != null) {
if (feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
if(filter.getValues().length > 0) {
if(feed.hasLastUpdateFailed()) {
if (filter.getValues().length > 0) {
if (feed.hasLastUpdateFailed()) {
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) txtvInformation.getLayoutParams();
p.addRule(RelativeLayout.BELOW, R.id.txtvFailure);
}
@ -460,15 +457,14 @@ public class FeedItemlistFragment extends ListFragment {
}
private void setupHeaderView() {
if (getListView() == null || feed == null) {
if (listView == null || feed == null) {
Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
ListView lv = getListView();
LayoutInflater inflater = (LayoutInflater)
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View header = inflater.inflate(R.layout.feeditemlist_header, lv, false);
lv.addHeaderView(header);
View header = inflater.inflate(R.layout.feeditemlist_header, listView, false);
listView.addHeaderView(header);
txtvTitle = header.findViewById(R.id.txtvTitle);
TextView txtvAuthor = header.findViewById(R.id.txtvAuthor);
@ -482,7 +478,6 @@ public class FeedItemlistFragment extends ListFragment {
txtvTitle.setText(feed.getTitle());
txtvAuthor.setText(feed.getAuthor());
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
@ -530,16 +525,15 @@ public class FeedItemlistFragment extends ListFragment {
private void setupFooterView() {
if (getListView() == null || feed == null) {
if (listView == null || feed == null) {
Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
if (feed.isPaged() && feed.getNextPageLink() != null) {
ListView lv = getListView();
LayoutInflater inflater = (LayoutInflater)
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View header = inflater.inflate(R.layout.more_content_list_footer, lv, false);
lv.addFooterView(header);
View header = inflater.inflate(R.layout.more_content_list_footer, listView, false);
listView.addFooterView(header);
listFooter = new MoreContentListFooterUtil(header);
listFooter.setClickListener(() -> {
if (feed != null) {
@ -573,7 +567,7 @@ public class FeedItemlistFragment extends ListFragment {
};
private void loadItems() {
if(disposable != null) {
if (disposable != null) {
disposable.dispose();
}
disposable = Observable.fromCallable(this::loadData)
@ -600,5 +594,4 @@ public class FeedItemlistFragment extends ListFragment {
}
return Optional.ofNullable(feed);
}
}

View File

@ -4,11 +4,18 @@ import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent;
import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent;
@ -34,17 +41,11 @@ import java.util.Locale;
import static de.danoeh.antennapod.core.feed.FeedPreferences.SPEED_USE_GLOBAL;
public class FeedSettingsFragment extends PreferenceFragmentCompat {
private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter";
private static final String PREF_FEED_PLAYBACK_SPEED = "feedPlaybackSpeed";
private static final DecimalFormat SPEED_FORMAT =
new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.US));
private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
public class FeedSettingsFragment extends Fragment {
private static final String TAG = "FeedSettingsFragment";
private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
private Feed feed;
private Disposable disposable;
private FeedPreferences feedPreferences;
public static FeedSettingsFragment newInstance(Feed feed) {
FeedSettingsFragment fragment = new FeedSettingsFragment();
@ -54,13 +55,20 @@ public class FeedSettingsFragment extends PreferenceFragmentCompat {
return fragment;
}
@Nullable
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.feed_settings);
setupAutoDownloadGlobalPreference(); // To prevent transition animation because of summary update
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.feedsettings, container, false);
long feedId = getArguments().getLong(EXTRA_FEED_ID);
Toolbar toolbar = root.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
getFragmentManager().beginTransaction()
.replace(R.id.settings_fragment_container,
FeedSettingsPreferenceFragment.newInstance(feedId), "settings_fragment")
.commitAllowingStateLoss();
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
Feed feed = DBReader.getFeed(feedId);
if (feed != null) {
@ -71,39 +79,12 @@ public class FeedSettingsFragment extends PreferenceFragmentCompat {
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
feed = result;
feedPreferences = feed.getPreferences();
((MainActivity) getActivity()).getSupportActionBar().setSubtitle(feed.getTitle());
.subscribe(result -> toolbar.setSubtitle(result.getTitle()),
error -> Log.d(TAG, Log.getStackTraceString(error)),
() -> { });
setupAutoDownloadPreference();
setupKeepUpdatedPreference();
setupAutoDeletePreference();
setupVolumeReductionPreferences();
setupAuthentificationPreference();
setupEpisodeFilterPreference();
setupPlaybackSpeedPreference();
updateAutoDeleteSummary();
updateVolumeReductionValue();
updateAutoDownloadEnabled();
updatePlaybackSpeedPreference();
}, error -> Log.d(TAG, Log.getStackTraceString(error)), () -> { });
}
@Override
public void onResume() {
super.onResume();
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.feed_settings_label);
if (feed != null) {
((MainActivity) getActivity()).getSupportActionBar().setSubtitle(feed.getTitle());
}
}
@Override
public void onStop() {
super.onStop();
((MainActivity) getActivity()).getSupportActionBar().setSubtitle(null);
return root;
}
@Override
@ -114,212 +95,275 @@ public class FeedSettingsFragment extends PreferenceFragmentCompat {
}
}
private void setupPlaybackSpeedPreference() {
ListPreference feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED);
public static class FeedSettingsPreferenceFragment extends PreferenceFragmentCompat {
private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter";
private static final String PREF_FEED_PLAYBACK_SPEED = "feedPlaybackSpeed";
private static final DecimalFormat SPEED_FORMAT =
new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.US));
final String[] speeds = getResources().getStringArray(R.array.playback_speed_values);
String[] values = new String[speeds.length + 1];
values[0] = SPEED_FORMAT.format(SPEED_USE_GLOBAL);
private Feed feed;
private Disposable disposable;
private FeedPreferences feedPreferences;
String[] entries = new String[speeds.length + 1];
entries[0] = getString(R.string.feed_auto_download_global);
System.arraycopy(speeds, 0, values, 1, speeds.length);
System.arraycopy(speeds, 0, entries, 1, speeds.length);
feedPlaybackSpeedPreference.setEntryValues(values);
feedPlaybackSpeedPreference.setEntries(entries);
feedPlaybackSpeedPreference.setOnPreferenceChangeListener((preference, newValue) -> {
feedPreferences.setFeedPlaybackSpeed(Float.parseFloat((String) newValue));
feed.savePreferences();
updatePlaybackSpeedPreference();
EventBus.getDefault().post(
new SpeedPresetChangedEvent(feedPreferences.getFeedPlaybackSpeed(), feed.getId()));
return false;
});
}
private void setupEpisodeFilterPreference() {
findPreference(PREF_EPISODE_FILTER).setOnPreferenceClickListener(preference -> {
new EpisodeFilterDialog(getContext(), feedPreferences.getFilter()) {
@Override
protected void onConfirmed(FeedFilter filter) {
feedPreferences.setFilter(filter);
feed.savePreferences();
}
}.show();
return false;
});
}
private void setupAuthentificationPreference() {
findPreference("authentication").setOnPreferenceClickListener(preference -> {
new AuthenticationDialog(getContext(),
R.string.authentication_label, true, false,
feedPreferences.getUsername(), feedPreferences.getPassword()) {
@Override
protected void onConfirmed(String username, String password, boolean saveUsernamePassword) {
feedPreferences.setUsername(username);
feedPreferences.setPassword(password);
feed.savePreferences();
}
}.show();
return false;
});
}
private void setupAutoDeletePreference() {
ListPreference autoDeletePreference = (ListPreference) findPreference("autoDelete");
autoDeletePreference.setOnPreferenceChangeListener((preference, newValue) -> {
switch ((String) newValue) {
case "global":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.GLOBAL);
break;
case "always":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.YES);
break;
case "never":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
break;
}
feed.savePreferences();
updateAutoDeleteSummary();
return false;
});
}
private void updatePlaybackSpeedPreference() {
ListPreference feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED);
float speedValue = feedPreferences.getFeedPlaybackSpeed();
feedPlaybackSpeedPreference.setValue(SPEED_FORMAT.format(speedValue));
}
private void updateAutoDeleteSummary() {
ListPreference autoDeletePreference = findPreference("autoDelete");
switch (feedPreferences.getAutoDeleteAction()) {
case GLOBAL:
autoDeletePreference.setSummary(R.string.feed_auto_download_global);
autoDeletePreference.setValue("global");
break;
case YES:
autoDeletePreference.setSummary(R.string.feed_auto_download_always);
autoDeletePreference.setValue("always");
break;
case NO:
autoDeletePreference.setSummary(R.string.feed_auto_download_never);
autoDeletePreference.setValue("never");
break;
}
}
private void setupVolumeReductionPreferences() {
ListPreference volumeReductionPreference = (ListPreference) findPreference("volumeReduction");
volumeReductionPreference.setOnPreferenceChangeListener((preference, newValue) -> {
switch ((String) newValue) {
case "off":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.OFF);
break;
case "light":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION);
break;
case "heavy":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.HEAVY_REDUCTION);
break;
}
feed.savePreferences();
updateVolumeReductionValue();
EventBus.getDefault().post(
new VolumeAdaptionChangedEvent(feedPreferences.getVolumeAdaptionSetting(), feed.getId()));
return false;
});
}
private void updateVolumeReductionValue() {
ListPreference volumeReductionPreference = (ListPreference) findPreference("volumeReduction");
switch (feedPreferences.getVolumeAdaptionSetting()) {
case OFF:
volumeReductionPreference.setValue("off");
break;
case LIGHT_REDUCTION:
volumeReductionPreference.setValue("light");
break;
case HEAVY_REDUCTION:
volumeReductionPreference.setValue("heavy");
break;
}
}
private void setupKeepUpdatedPreference() {
SwitchPreference pref = (SwitchPreference) findPreference("keepUpdated");
pref.setChecked(feedPreferences.getKeepUpdated());
pref.setOnPreferenceChangeListener((preference, newValue) -> {
boolean checked = newValue == Boolean.TRUE;
feedPreferences.setKeepUpdated(checked);
feed.savePreferences();
pref.setChecked(checked);
return false;
});
}
private void setupAutoDownloadGlobalPreference() {
if (!UserPreferences.isEnableAutodownload()) {
SwitchPreference autodl = findPreference("autoDownload");
autodl.setChecked(false);
autodl.setEnabled(false);
autodl.setSummary(R.string.auto_download_disabled_globally);
findPreference(PREF_EPISODE_FILTER).setEnabled(false);
}
}
private void setupAutoDownloadPreference() {
SwitchPreference pref = (SwitchPreference) findPreference("autoDownload");
pref.setEnabled(UserPreferences.isEnableAutodownload());
if (UserPreferences.isEnableAutodownload()) {
pref.setChecked(feedPreferences.getAutoDownload());
} else {
pref.setChecked(false);
pref.setSummary(R.string.auto_download_disabled_globally);
}
pref.setOnPreferenceChangeListener((preference, newValue) -> {
boolean checked = newValue == Boolean.TRUE;
feedPreferences.setAutoDownload(checked);
feed.savePreferences();
updateAutoDownloadEnabled();
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(getActivity(), checked);
dialog.createNewDialog().show();
pref.setChecked(checked);
return false;
});
}
private void updateAutoDownloadEnabled() {
if (feed != null && feed.getPreferences() != null) {
boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
findPreference(PREF_EPISODE_FILTER).setEnabled(enabled);
}
}
private class ApplyToEpisodesDialog extends ConfirmationDialog {
private final boolean autoDownload;
ApplyToEpisodesDialog(Context context, boolean autoDownload) {
super(context, R.string.auto_download_apply_to_items_title,
R.string.auto_download_apply_to_items_message);
this.autoDownload = autoDownload;
setPositiveText(R.string.yes);
setNegativeText(R.string.no);
public static FeedSettingsPreferenceFragment newInstance(long feedId) {
FeedSettingsPreferenceFragment fragment = new FeedSettingsPreferenceFragment();
Bundle arguments = new Bundle();
arguments.putLong(EXTRA_FEED_ID, feedId);
fragment.setArguments(arguments);
return fragment;
}
@Override
public void onConfirmButtonPressed(DialogInterface dialog) {
DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.feed_settings);
setupAutoDownloadGlobalPreference(); // To prevent transition animation because of summary update
long feedId = getArguments().getLong(EXTRA_FEED_ID);
disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> {
Feed feed = DBReader.getFeed(feedId);
if (feed != null) {
emitter.onSuccess(feed);
} else {
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
feed = result;
feedPreferences = feed.getPreferences();
setupAutoDownloadPreference();
setupKeepUpdatedPreference();
setupAutoDeletePreference();
setupVolumeReductionPreferences();
setupAuthentificationPreference();
setupEpisodeFilterPreference();
setupPlaybackSpeedPreference();
updateAutoDeleteSummary();
updateVolumeReductionValue();
updateAutoDownloadEnabled();
updatePlaybackSpeedPreference();
}, error -> Log.d(TAG, Log.getStackTraceString(error)), () -> { });
}
@Override
public void onDestroy() {
super.onDestroy();
if (disposable != null) {
disposable.dispose();
}
}
private void setupPlaybackSpeedPreference() {
ListPreference feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED);
final String[] speeds = getResources().getStringArray(R.array.playback_speed_values);
String[] values = new String[speeds.length + 1];
values[0] = SPEED_FORMAT.format(SPEED_USE_GLOBAL);
String[] entries = new String[speeds.length + 1];
entries[0] = getString(R.string.feed_auto_download_global);
System.arraycopy(speeds, 0, values, 1, speeds.length);
System.arraycopy(speeds, 0, entries, 1, speeds.length);
feedPlaybackSpeedPreference.setEntryValues(values);
feedPlaybackSpeedPreference.setEntries(entries);
feedPlaybackSpeedPreference.setOnPreferenceChangeListener((preference, newValue) -> {
feedPreferences.setFeedPlaybackSpeed(Float.parseFloat((String) newValue));
feed.savePreferences();
updatePlaybackSpeedPreference();
EventBus.getDefault().post(
new SpeedPresetChangedEvent(feedPreferences.getFeedPlaybackSpeed(), feed.getId()));
return false;
});
}
private void setupEpisodeFilterPreference() {
findPreference(PREF_EPISODE_FILTER).setOnPreferenceClickListener(preference -> {
new EpisodeFilterDialog(getContext(), feedPreferences.getFilter()) {
@Override
protected void onConfirmed(FeedFilter filter) {
feedPreferences.setFilter(filter);
feed.savePreferences();
}
}.show();
return false;
});
}
private void setupAuthentificationPreference() {
findPreference("authentication").setOnPreferenceClickListener(preference -> {
new AuthenticationDialog(getContext(),
R.string.authentication_label, true, false,
feedPreferences.getUsername(), feedPreferences.getPassword()) {
@Override
protected void onConfirmed(String username, String password, boolean saveUsernamePassword) {
feedPreferences.setUsername(username);
feedPreferences.setPassword(password);
feed.savePreferences();
}
}.show();
return false;
});
}
private void setupAutoDeletePreference() {
ListPreference autoDeletePreference = findPreference("autoDelete");
autoDeletePreference.setOnPreferenceChangeListener((preference, newValue) -> {
switch ((String) newValue) {
case "global":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.GLOBAL);
break;
case "always":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.YES);
break;
case "never":
feedPreferences.setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
break;
}
feed.savePreferences();
updateAutoDeleteSummary();
return false;
});
}
private void updatePlaybackSpeedPreference() {
ListPreference feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED);
float speedValue = feedPreferences.getFeedPlaybackSpeed();
feedPlaybackSpeedPreference.setValue(SPEED_FORMAT.format(speedValue));
}
private void updateAutoDeleteSummary() {
ListPreference autoDeletePreference = findPreference("autoDelete");
switch (feedPreferences.getAutoDeleteAction()) {
case GLOBAL:
autoDeletePreference.setSummary(R.string.feed_auto_download_global);
autoDeletePreference.setValue("global");
break;
case YES:
autoDeletePreference.setSummary(R.string.feed_auto_download_always);
autoDeletePreference.setValue("always");
break;
case NO:
autoDeletePreference.setSummary(R.string.feed_auto_download_never);
autoDeletePreference.setValue("never");
break;
}
}
private void setupVolumeReductionPreferences() {
ListPreference volumeReductionPreference = findPreference("volumeReduction");
volumeReductionPreference.setOnPreferenceChangeListener((preference, newValue) -> {
switch ((String) newValue) {
case "off":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.OFF);
break;
case "light":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION);
break;
case "heavy":
feedPreferences.setVolumeAdaptionSetting(VolumeAdaptionSetting.HEAVY_REDUCTION);
break;
}
feed.savePreferences();
updateVolumeReductionValue();
EventBus.getDefault().post(
new VolumeAdaptionChangedEvent(feedPreferences.getVolumeAdaptionSetting(), feed.getId()));
return false;
});
}
private void updateVolumeReductionValue() {
ListPreference volumeReductionPreference = findPreference("volumeReduction");
switch (feedPreferences.getVolumeAdaptionSetting()) {
case OFF:
volumeReductionPreference.setValue("off");
break;
case LIGHT_REDUCTION:
volumeReductionPreference.setValue("light");
break;
case HEAVY_REDUCTION:
volumeReductionPreference.setValue("heavy");
break;
}
}
private void setupKeepUpdatedPreference() {
SwitchPreference pref = findPreference("keepUpdated");
pref.setChecked(feedPreferences.getKeepUpdated());
pref.setOnPreferenceChangeListener((preference, newValue) -> {
boolean checked = newValue == Boolean.TRUE;
feedPreferences.setKeepUpdated(checked);
feed.savePreferences();
pref.setChecked(checked);
return false;
});
}
private void setupAutoDownloadGlobalPreference() {
if (!UserPreferences.isEnableAutodownload()) {
SwitchPreference autodl = findPreference("autoDownload");
autodl.setChecked(false);
autodl.setEnabled(false);
autodl.setSummary(R.string.auto_download_disabled_globally);
findPreference(PREF_EPISODE_FILTER).setEnabled(false);
}
}
private void setupAutoDownloadPreference() {
SwitchPreference pref = findPreference("autoDownload");
pref.setEnabled(UserPreferences.isEnableAutodownload());
if (UserPreferences.isEnableAutodownload()) {
pref.setChecked(feedPreferences.getAutoDownload());
} else {
pref.setChecked(false);
pref.setSummary(R.string.auto_download_disabled_globally);
}
pref.setOnPreferenceChangeListener((preference, newValue) -> {
boolean checked = newValue == Boolean.TRUE;
feedPreferences.setAutoDownload(checked);
feed.savePreferences();
updateAutoDownloadEnabled();
ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(getActivity(), checked);
dialog.createNewDialog().show();
pref.setChecked(checked);
return false;
});
}
private void updateAutoDownloadEnabled() {
if (feed != null && feed.getPreferences() != null) {
boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
findPreference(PREF_EPISODE_FILTER).setEnabled(enabled);
}
}
private class ApplyToEpisodesDialog extends ConfirmationDialog {
private final boolean autoDownload;
ApplyToEpisodesDialog(Context context, boolean autoDownload) {
super(context, R.string.auto_download_apply_to_items_title,
R.string.auto_download_apply_to_items_message);
this.autoDownload = autoDownload;
setPositiveText(R.string.yes);
setNegativeText(R.string.no);
}
@Override
public void onConfirmButtonPressed(DialogInterface dialog) {
DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
}
}
}
}

View File

@ -9,6 +9,8 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentStatePagerAdapter;
@ -77,6 +79,9 @@ public class ItemPagerFragment extends Fragment {
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View layout = inflater.inflate(R.layout.feeditem_pager_fragment, container, false);
Toolbar toolbar = layout.findViewById(R.id.toolbar);
toolbar.setTitle("");
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
feedItems = getArguments().getLongArray(ARG_FEEDITEMS);
int feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS);
@ -145,15 +150,12 @@ public class ItemPagerFragment extends Fragment {
((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
inflater.inflate(R.menu.feeditem_options, menu);
if (menu != null && item != null) {
if (item.hasMedia()) {
FeedItemMenuHandler.onPrepareMenu(menu, item);
} else {
// these are already available via button1 and button2
FeedItemMenuHandler.onPrepareMenu(menu, item,
R.id.mark_read_item, R.id.visit_website_item);
}
if (item.hasMedia()) {
FeedItemMenuHandler.onPrepareMenu(menu, item);
} else {
// these are already available via button1 and button2
FeedItemMenuHandler.onPrepareMenu(menu, item,
R.id.mark_read_item, R.id.visit_website_item);
}
}

View File

@ -2,50 +2,50 @@ package de.danoeh.antennapod.fragment;
import android.content.res.TypedArray;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import androidx.core.view.MenuItemCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.event.PlaybackHistoryEvent;
import de.danoeh.antennapod.core.event.PlayerStatusEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class PlaybackHistoryFragment extends ListFragment {
public class PlaybackHistoryFragment extends Fragment implements AdapterView.OnItemClickListener {
public static final String TAG = "PlaybackHistoryFragment";
private List<FeedItem> playbackHistory;
private FeedItemlistAdapter adapter;
private List<Downloader> downloaderList;
private Disposable disposable;
private ListView listView;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -55,26 +55,26 @@ public class PlaybackHistoryFragment extends ListFragment {
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// add padding
final ListView lv = getListView();
lv.setClipToPadding(false);
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding);
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.simple_list_fragment, container, false);
Toolbar toolbar = root.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.playback_history_label);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
listView = root.findViewById(android.R.id.list);
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setIcon(R.attr.ic_history);
emptyView.setTitle(R.string.no_history_head_label);
emptyView.setMessage(R.string.no_history_label);
emptyView.attachToListView(getListView());
emptyView.attachToListView(listView);
// played items shoudln't be transparent for this fragment since, *all* items
// in this fragment will, by definition, be played. So it serves no purpose and can make
// it harder to read.
adapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, true, false);
setListAdapter(adapter);
listView.setAdapter(adapter);
return root;
}
@Override
@ -96,15 +96,12 @@ public class PlaybackHistoryFragment extends ListFragment {
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update;
downloaderList = update.downloaders;
adapter.notifyDataSetChanged();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
position -= l.getHeaderViewsCount();
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
position -= listView.getHeaderViewsCount();
long[] ids = FeedItemUtil.getIds(playbackHistory);
((MainActivity) getActivity()).loadChildFragment(ItemPagerFragment.newInstance(ids, position));
}
@ -149,12 +146,12 @@ public class PlaybackHistoryFragment extends ListFragment {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if(playbackHistory == null) {
if (playbackHistory == null) {
return;
}
for(FeedItem item : event.items) {
for (FeedItem item : event.items) {
int pos = FeedItemUtil.indexOfItemWithId(playbackHistory, item.getId());
if(pos >= 0) {
if (pos >= 0) {
loadItems();
return;
}
@ -196,7 +193,7 @@ public class PlaybackHistoryFragment extends ListFragment {
};
private void loadItems() {
if(disposable != null) {
if (disposable != null) {
disposable.dispose();
}
disposable = Observable.fromCallable(this::loadData)

View File

@ -16,6 +16,7 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
@ -495,9 +496,8 @@ public class QueueFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.queue_label);
View root = inflater.inflate(R.layout.queue_fragment, container, false);
((AppCompatActivity) getActivity()).setSupportActionBar(root.findViewById(R.id.toolbar));
infoBar = root.findViewById(R.id.info_bar);
recyclerView = root.findViewById(R.id.recyclerView);
RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();

View File

@ -103,9 +103,8 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
View layout = inflater.inflate(R.layout.search_fragment, container, false);
((AppCompatActivity) getActivity()).setSupportActionBar(layout.findViewById(R.id.toolbar));
ListView listView = layout.findViewById(R.id.listview);
progressBar = layout.findViewById(R.id.progressBar);
searchAdapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, true, true);
@ -141,7 +140,7 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
item.setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
final SearchView sv = new SearchView(getActivity());
sv.setQueryHint(getString(R.string.search_label));
sv.setQuery(getArguments().getString(ARG_QUERY), false);
@ -159,7 +158,8 @@ public class SearchFragment extends Fragment implements AdapterView.OnItemClickL
return false;
}
});
MenuItemCompat.setActionView(item, sv);
sv.setIconifiedByDefault(false);
item.setActionView(sv);
}
@Subscribe

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.ContextMenu;
@ -85,6 +86,7 @@ public class SubscriptionFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_subscriptions, container, false);
((AppCompatActivity) getActivity()).setSupportActionBar(root.findViewById(R.id.toolbar));
subscriptionGridLayout = root.findViewById(R.id.subscriptions_grid);
subscriptionGridLayout.setNumColumns(prefs.getInt(PREF_NUM_COLUMNS, 3));
registerForContextMenu(subscriptionGridLayout);
@ -160,10 +162,6 @@ public class SubscriptionFragment extends Fragment {
((MainActivity) getActivity()).loadChildFragment(new AddFeedFragment());
}
});
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.subscriptions_label);
}
}
@Override

View File

@ -49,6 +49,8 @@ public class StatisticsFragment extends Fragment {
tabLayout = rootView.findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
rootView.findViewById(R.id.toolbar).setVisibility(View.GONE);
return rootView;
}

View File

@ -1,182 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
android:layout_height="match_parent" android:layout_width="match_parent"
android:orientation="vertical">
<LinearLayout
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:focusableInTouchMode="true"
android:padding="8dp">
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:title="@string/add_feed_label"
android:id="@+id/toolbar"/>
<androidx.cardview.widget.CardView
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:elevation="16dp"
android:layout_margin="8dp">
android:orientation="vertical"
android:focusableInTouchMode="true"
android:padding="8dp">
<LinearLayout
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
app:cardCornerRadius="4dp"
android:elevation="16dp"
android:layout_margin="8dp">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:contentDescription="@string/search_podcast_hint"
app:srcCompat="?attr/action_search"
android:id="@+id/search_icon"
android:scaleType="center"/>
<EditText
android:id="@+id/combinedFeedSearchBox"
android:layout_width="0dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:hint="@string/search_podcast_hint"
android:background="@null"/>
android:orientation="horizontal">
</LinearLayout>
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:contentDescription="@string/search_podcast_hint"
app:srcCompat="?attr/action_search"
android:id="@+id/search_icon"
android:scaleType="center"/>
</androidx.cardview.widget.CardView>
<EditText
android:id="@+id/combinedFeedSearchBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:hint="@string/search_podcast_hint"
android:background="@null"/>
<fragment
android:id="@+id/quickFeedDiscovery"
android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"/>
</LinearLayout>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:elevation="8dp"
android:layout_margin="8dp">
</androidx.cardview.widget.CardView>
<LinearLayout
<fragment
android:id="@+id/quickFeedDiscovery"
android:name="de.danoeh.antennapod.fragment.QuickFeedDiscoveryFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
android:layout_margin="8dp"/>
<TextView
android:id="@+id/txtvFeedurl"
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:elevation="8dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/txtvfeedurl_label"
android:textSize="18sp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textColor="?android:attr/textColorPrimary"/>
android:padding="16dp"
android:orientation="vertical">
<EditText
android:id="@+id/etxtFeedurl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cursorVisible="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/etxtFeedurlHint"
android:inputType="textUri"/>
<TextView
android:id="@+id/txtvFeedurl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/txtvfeedurl_label"
android:textSize="18sp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textColor="?android:attr/textColorPrimary"/>
<Button
android:id="@+id/butConfirm"
<EditText
android:id="@+id/etxtFeedurl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cursorVisible="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:hint="@string/etxtFeedurlHint"
android:inputType="textUri"/>
<Button
android:id="@+id/butConfirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/confirm_label"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:elevation="8dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
style="?android:attr/buttonBarButtonStyle"
android:text="@string/confirm_label"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
android:elevation="8dp"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/advanced_search"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:contentDescription="@string/advanced_search"
app:srcCompat="?attr/action_search"
android:scaleType="center"
android:layout_marginBottom="4dp"/>
<TextView
android:layout_width="match_parent"
<LinearLayout
android:id="@+id/advanced_search"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="@string/advanced_search"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
<LinearLayout
android:id="@+id/btn_opml_import"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:contentDescription="@string/advanced_search"
app:srcCompat="?attr/action_search"
android:scaleType="center"
android:layout_marginBottom="4dp"/>
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:contentDescription="@string/opml_import_label"
app:srcCompat="?attr/av_download"
android:scaleType="center"
android:layout_marginBottom="4dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/advanced_search"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
<LinearLayout
android:id="@+id/btn_opml_import"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="@string/opml_import_label"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"/>
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:contentDescription="@string/opml_import_label"
app:srcCompat="?attr/av_download"
android:scaleType="center"
android:layout_marginBottom="4dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/opml_import_label"
android:textAlignment="center"
android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@ -4,17 +4,27 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
app:navigationIcon="?homeAsUpIndicator"
android:id="@+id/toolbar"/>
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_below="@id/toolbar"
android:layout_marginTop="0dp" />
<com.leinardi.android.speeddial.SpeedDialOverlayLayout
android:id="@+id/fabSDOverlay"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:layout_below="@id/toolbar" />
<!-- The FAB SpeedDial
1. MUST be placed at the bottom of the layout xml to ensure it is at the front,
clickable on Pre-Lollipop devices (that do not support elevation).

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
android:id="@+id/toolbar"/>
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:id="@android:id/list"/>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="gone"/>
</RelativeLayout>

View File

@ -1,132 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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">
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent">
<include layout="@layout/feeditemlist_header" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbarStyle="outsideOverlay"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:clipToPadding="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/imgvBackground"
style="@style/BigBlurryBackground"
android:layout_width="match_parent"
android:layout_height="256dp"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>
<include layout="@layout/feeditemlist_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:navigationIcon="?homeAsUpIndicator"
android:layout_alignParentTop="true"
android:id="@+id/toolbar"
app:layout_collapseMode="pin"/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.gridlayout.widget.GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:columnCount="2"
app:rowCount="3">
android:orientation="vertical">
<TextView
<TextView
style="@style/AntennaPod.TextView.Heading"
android:id="@+id/lblAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_row="0"
app:layout_column="0"
android:lines="1"
android:text="@string/author_label"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light"/>
<TextView
<TextView
android:id="@+id/txtvDetailsAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
app:layout_row="0"
app:layout_column="1"
tools:text="Daniel Oeh"
tools:background="@android:color/holo_green_dark"/>
<TextView
<TextView
style="@style/AntennaPod.TextView.Heading"
android:id="@+id/lblLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_row="1"
app:layout_column="0"
android:lines="1"
android:text="@string/language_label"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light"/>
<TextView
<TextView
android:id="@+id/txtvLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
app:layout_row="1"
app:layout_column="1"
tools:text="English"
tools:background="@android:color/holo_green_dark"/>
<TextView
<TextView
style="@style/AntennaPod.TextView.Heading"
android:id="@+id/lblUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_marginEnd="8dp"
app:layout_row="2"
app:layout_column="0"
android:lines="1"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:text="@string/url_label"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light"/>
<TextView
<TextView
android:id="@+id/txtvUrl"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
android:background="?attr/selectableItemBackground"
app:layout_row="2"
app:layout_column="1"
app:layout_gravity="fill"
android:maxLines="4"
android:paddingTop="4dp"
android:paddingBottom="4dp"
tools:text="http://www.example.com/feed"
tools:background="@android:color/holo_green_dark"/>
</androidx.gridlayout.widget.GridLayout>
<TextView
style="@style/AntennaPod.TextView.Heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:text="@string/description_label"/>
<TextView
style="@style/AntennaPod.TextView.Heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/description_label"/>
<TextView
android:id="@+id/txtvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textIsSelectable="true"
android:text="@string/design_time_lorem_ipsum"
tools:background="@android:color/holo_green_dark"/>
android:id="@+id/txtvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:text="@string/design_time_lorem_ipsum"
tools:background="@android:color/holo_green_dark"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</ScrollView>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -18,7 +18,6 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<ImageView

View File

@ -1,6 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:navigationIcon="?homeAsUpIndicator"
android:id="@+id/toolbar"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -1,10 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/feeditemlist_header" />
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:title="@string/feed_settings_label"
app:navigationIcon="?homeAsUpIndicator"
android:elevation="4dp"
android:id="@+id/toolbar"/>
<FrameLayout
android:layout_width="match_parent"

View File

@ -1,10 +1,21 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
app:navigationIcon="?homeAsUpIndicator"
app:title="@string/discover"
android:id="@+id/toolbar"/>
<GridView
android:layout_below="@id/toolbar"
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@ -1,28 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
app:title="@string/subscriptions_label"
android:id="@+id/toolbar"/>
<GridView
android:layout_below="@id/toolbar"
android:id="@+id/subscriptions_grid"
android:layout_width="match_parent"
android:numColumns="3"
android:horizontalSpacing="2dp"
android:verticalSpacing="2dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:paddingBottom="88dp"
android:clipToPadding="false"/>
<GridView
android:id="@+id/subscriptions_grid"
android:layout_width="match_parent"
android:numColumns="3"
android:horizontalSpacing="2dp"
android:verticalSpacing="2dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:paddingBottom="88dp"
android:clipToPadding="false">
</GridView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/subscriptions_add"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:contentDescription="@string/add_feed_label"
android:src="@drawable/ic_add_white_24dp"
/>
</FrameLayout>
android:src="@drawable/ic_add_white_24dp"/>
</RelativeLayout>

View File

@ -19,28 +19,12 @@
tools:layout_height="64dp"
tools:background="@android:color/holo_green_light" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
tools:background="@android:color/holo_blue_dark" />
<View
android:id="@+id/shadow"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_below="@id/toolbar"
android:background="@drawable/shadow" />
<FrameLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_above="@id/playerFragment"
android:layout_below="@id/toolbar"
android:layout_alignParentTop="true"
android:foreground="?android:windowContentOverlay"
tools:background="@android:color/holo_red_dark" />

View File

@ -1,22 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:id="@+id/toolbar"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"
app:tabMode="fixed" />
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -1,17 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
app:title="@string/queue_label"
android:id="@+id/toolbar"/>
<TextView
android:layout_below="@id/toolbar"
android:id="@+id/info_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center"
android:textSize="12sp"
android:text=""/>
android:layout_marginTop="-8dp"
android:layout_marginLeft="72dp"
android:layout_marginStart="72dp"
android:layout_marginBottom="4dp"
tools:text="12 Episodes - Time remaining: 12 hours"/>
<View
android:id="@+id/divider"

View File

@ -1,17 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:navigationIcon="?homeAsUpIndicator"
app:title="@string/search_label"
android:id="@+id/toolbar"/>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
android:layout_centerInParent="true"
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
android:layout_below="@id/toolbar"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
android:layout_alignParentTop="true"
android:id="@+id/toolbar"/>
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:id="@android:id/list"
android:clipToPadding="false"/>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminateOnly="true"
android:visibility="gone"/>
</RelativeLayout>

View File

@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto">
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/episode_actions"
android:menuCategory="container"
android:title="@string/multi_select"
android:icon="?attr/checkbox_multiple"
custom:showAsAction="always">
</item>
android:showAsAction="ifRoom" />
</menu>

View File

@ -13,7 +13,7 @@ public class MenuItemUtils {
/**
* Changes the appearance of a MenuItem depending on whether the given UpdateRefreshMenuItemChecker
* is refreshing or not. If it returns true, the menu item will be replaced by an indeterminate progress
* bar, otherwise nothing will happen.
* bar, otherwise the progress bar will be hidden.
*
* @param menu The menu that the MenuItem belongs to
* @param resId The id of the MenuItem
@ -22,11 +22,12 @@ public class MenuItemUtils {
*/
public static boolean updateRefreshMenuItem(Menu menu, int resId, UpdateRefreshMenuItemChecker checker) {
// expand actionview if feeds are being downloaded, collapse otherwise
MenuItem refreshItem = menu.findItem(resId);
if (checker.isRefreshing()) {
MenuItem refreshItem = menu.findItem(resId);
refreshItem.setActionView(R.layout.refresh_action_view);
return true;
} else {
refreshItem.setActionView(null);
return false;
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:indeterminateOnly="true">
</ProgressBar>
<ProgressBar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end"
android:padding="8dp"
android:indeterminateOnly="true"/>