Added collapsing feed info

This commit is contained in:
ByteHamster 2020-03-12 22:11:07 +01:00
parent 7f4d43deb1
commit 32dd30705a
8 changed files with 406 additions and 185 deletions

View File

@ -141,6 +141,7 @@ dependencies {
implementation "androidx.preference:preference:1.1.0"
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.recyclerview:recyclerview:1.0.0"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
implementation "androidx.media:media:1.1.0"
implementation "com.google.android.material:material:1.0.0"
annotationProcessor "androidx.annotation:annotation:1.1.0"

View File

@ -368,8 +368,6 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
ImageView cover = findViewById(R.id.imgvCover);
ImageView headerBackground = findViewById(R.id.imgvBackground);
findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
headerBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
TextView title = findViewById(R.id.txtvTitle);
TextView author = findViewById(R.id.txtvAuthor);

View File

@ -29,6 +29,8 @@ import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
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.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView;
import de.danoeh.antennapod.R;
@ -58,12 +60,14 @@ 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.Optional;
import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.ToolbarIconTintManager;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@ -86,19 +90,23 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
private MoreContentListFooterUtil listFooter;
private long feedID;
private Feed feed;
private boolean headerCreated = false;
private boolean isUpdatingFeed;
private ProgressBar progressBar;
private ListView listView;
private TextView txtvTitle;
private IconTextView txtvFailure;
private ImageView imgvBackground;
private ImageView imgvCover;
private TextView txtvInformation;
private ListView listView;
private ProgressBar progressBar;
private TextView txtvAuthor;
private ImageButton butShowInfo;
private ImageButton butShowSettings;
private Menu optionsMenu;
private ToolbarIconTintManager iconTintManager;
private long feedID;
private Feed feed;
private boolean headerCreated = false;
private boolean isUpdatingFeed;
private Disposable disposable;
/**
@ -140,7 +148,34 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
listView.setOnItemClickListener(this);
registerForContextMenu(listView);
progressBar = root.findViewById(R.id.progLoading);
txtvTitle = root.findViewById(R.id.txtvTitle);
txtvAuthor = root.findViewById(R.id.txtvAuthor);
imgvBackground = root.findViewById(R.id.imgvBackground);
imgvCover = root.findViewById(R.id.imgvCover);
butShowInfo = root.findViewById(R.id.butShowInfo);
butShowSettings = root.findViewById(R.id.butShowSettings);
txtvInformation = root.findViewById(R.id.txtvInformation);
txtvFailure = root.findViewById(R.id.txtvFailure);
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.sort_items)
.setIcon(ThemeUtils.getDrawableFromAttr(themedContext, R.attr.ic_sort));
optionsMenu.findItem(R.id.filter_items)
.setIcon(ThemeUtils.getDrawableFromAttr(themedContext, R.attr.ic_filter));
optionsMenu.findItem(R.id.refresh_item)
.setIcon(ThemeUtils.getDrawableFromAttr(themedContext, R.attr.navigation_refresh));
optionsMenu.findItem(R.id.action_search)
.setIcon(ThemeUtils.getDrawableFromAttr(themedContext, R.attr.action_search));
}
};
appBar.addOnOffsetChangedListener(iconTintManager);
EventBus.getDefault().register(this);
loadItems();
return root;
@ -171,8 +206,9 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
return;
}
super.onCreateOptionsMenu(menu, inflater);
optionsMenu = menu;
FeedMenuHandler.onCreateOptionsMenu(inflater, menu);
iconTintManager.updateTint();
MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
@ -285,9 +321,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
// because of addHeaderView(), positions are increased by 1!
FeedItem item = (FeedItem) itemAccess.getItem(adapterInfo.position - 1);
FeedItem item = (FeedItem) itemAccess.getItem(adapterInfo.position);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.feeditemlist_context, menu);
@ -305,8 +339,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
if (menuInfo == null) {
menuInfo = lastMenuInfo;
}
// because of addHeaderView(), positions are increased by 1!
FeedItem selectedItem = feed.getItemAtIndex(menuInfo.position - 1);
FeedItem selectedItem = feed.getItemAtIndex(menuInfo.position);
if (selectedItem == null) {
Log.i(TAG, "Selected item at position " + menuInfo.position + " was null, ignoring selection");
@ -321,7 +354,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
if (adapter == null) {
return;
}
position -= listView.getHeaderViewsCount();
MainActivity activity = (MainActivity) getActivity();
long[] ids = FeedItemUtil.getIds(feed.getItems());
activity.loadChildFragment(ItemPagerFragment.newInstance(ids, position));
@ -370,7 +402,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
}
private void updateUi() {
refreshHeaderView();
loadItems();
updateProgressBarVisibility();
}
@ -388,6 +419,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
@Subscribe(threadMode = ThreadMode.MAIN)
public void onFeedListChanged(FeedListUpdateEvent event) {
if (event.contains(feed)) {
refreshHeaderView();
updateUi();
}
}
@ -399,7 +431,6 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
if (listFooter != null) {
listFooter.setLoadingState(DownloadRequester.getInstance().isDownloadingFeeds());
}
}
private void displayList() {
@ -409,12 +440,10 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
}
if (adapter == null) {
listView.setAdapter(null);
setupHeaderView();
setupFooterView();
adapter = new FeedItemlistAdapter((MainActivity) getActivity(), itemAccess, false, true);
listView.setAdapter(adapter);
}
refreshHeaderView();
listView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
@ -438,6 +467,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
txtvFailure.setVisibility(View.GONE);
}
txtvTitle.setText(feed.getTitle());
txtvAuthor.setText(feed.getAuthor());
if (feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
if (filter.getValues().length > 0) {
@ -461,28 +491,12 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
LayoutInflater inflater = (LayoutInflater)
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
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);
imgvBackground = header.findViewById(R.id.imgvBackground);
imgvCover = header.findViewById(R.id.imgvCover);
ImageButton butShowInfo = header.findViewById(R.id.butShowInfo);
ImageButton butShowSettings = header.findViewById(R.id.butShowSettings);
txtvInformation = header.findViewById(R.id.txtvInformation);
txtvFailure = header.findViewById(R.id.txtvFailure);
txtvTitle.setText(feed.getTitle());
txtvAuthor.setText(feed.getAuthor());
if (headerCreated) {
return;
}
// https://github.com/bumptech/glide/issues/529
imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
loadFeedImage();
imgvBackground.setColorFilter(new LightingColorFilter(0xff666666, 0x000000));
butShowInfo.setOnClickListener(v -> showFeedInfo());
imgvCover.setOnClickListener(v -> showFeedInfo());
butShowSettings.setOnClickListener(v -> {
@ -492,6 +506,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
}
});
headerCreated = true;
refreshHeaderView();
}
private void showFeedInfo() {
@ -575,6 +590,7 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
feed = result.orElse(null);
setupHeaderView();
displayList();
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}

View File

@ -0,0 +1,74 @@
package de.danoeh.antennapod.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
import androidx.core.view.NestedScrollingChild;
import androidx.core.view.NestedScrollingChildHelper;
/**
* ListView that can be wrapped in NestedScrollView
* Based on https://stackoverflow.com/a/34920961.
*/
public class NestedScrollingListView extends ListView implements NestedScrollingChild {
private final NestedScrollingChildHelper nestedScrollingChildHelper;
public NestedScrollingListView(Context context) {
super(context);
nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
public NestedScrollingListView(Context context, AttributeSet attrs) {
super(context, attrs);
nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
setNestedScrollingEnabled(true);
}
@Override
public void setNestedScrollingEnabled(boolean enabled) {
nestedScrollingChildHelper.setNestedScrollingEnabled(enabled);
}
@Override
public boolean isNestedScrollingEnabled() {
return nestedScrollingChildHelper.isNestedScrollingEnabled();
}
@Override
public boolean startNestedScroll(int axes) {
return nestedScrollingChildHelper.startNestedScroll(axes);
}
@Override
public void stopNestedScroll() {
nestedScrollingChildHelper.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
return nestedScrollingChildHelper.hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
int dyUnconsumed, int[] offsetInWindow) {
return nestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return nestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return nestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return nestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}
}

View File

@ -0,0 +1,50 @@
package de.danoeh.antennapod.view;
import android.content.Context;
import android.graphics.PorterDuff;
import android.view.ContextThemeWrapper;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import de.danoeh.antennapod.R;
public abstract class ToolbarIconTintManager implements AppBarLayout.OnOffsetChangedListener {
private final Context context;
private final CollapsingToolbarLayout collapsingToolbar;
private final Toolbar toolbar;
private boolean isTinted = false;
public ToolbarIconTintManager(Context context, Toolbar toolbar, CollapsingToolbarLayout collapsingToolbar) {
this.context = context;
this.collapsingToolbar = collapsingToolbar;
this.toolbar = toolbar;
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
boolean tint = (collapsingToolbar.getHeight() + offset) > (2 * ViewCompat.getMinimumHeight(collapsingToolbar));
if (isTinted != tint) {
isTinted = tint;
updateTint();
}
}
public void updateTint() {
if (isTinted) {
doTint(new ContextThemeWrapper(context, R.style.Theme_AntennaPod_Dark));
//toolbar.getNavigationIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP);
toolbar.getOverflowIcon().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_ATOP);
} else {
doTint(context);
//toolbar.getNavigationIcon().clearColorFilter();
toolbar.getOverflowIcon().clearColorFilter();
}
}
/**
* View expansion was changed. Icons need to be tinted
* @param themedContext ContextThemeWrapper with dark theme while expanded
*/
protected abstract void doTint(Context themedContext);
}

View File

@ -1,27 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout
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">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<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"
android:layout_alignParentTop="true"
android:id="@+id/toolbar"/>
android:id="@+id/toolbar"
app:layout_collapseMode="pin"/>
<ListView android:layout_width="match_parent"
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<de.danoeh.antennapod.view.NestedScrollingListView
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
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:layout_gravity="center"
android:indeterminateOnly="true"
android:visibility="gone"/>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,51 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/feed_image_bg"
tools:context="de.danoeh.antennapod.activity.MainActivity"
tools:background="@android:color/darker_gray">
android:orientation="vertical">
<ImageView
android:id="@+id/imgvBackground"
style="@style/BigBlurryBackground"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/feeditemlist_header_height" />
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:layout_marginBottom="16dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/imgvCover"
android:layout_width="@dimen/thumbnail_length_onlinefeedview"
android:layout_height="@dimen/thumbnail_length_onlinefeedview"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:contentDescription="@string/cover_label"
tools:src="@drawable/ic_antenna"
tools:background="@android:color/holo_green_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.Heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:shadowColor="@color/black"
android:shadowRadius="2"
android:textColor="@color/white"
tools:text="Podcast title"
tools:background="@android:color/holo_green_dark"/>
<TextView
android:id="@+id/txtvAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:shadowColor="@color/black"
android:shadowRadius="2"
android:textColor="@color/white"
android:textSize="@dimen/text_size_small"
tools:text="Podcast author"
tools:background="@android:color/holo_green_dark"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="@+id/butShowInfo"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackground"
android:contentDescription="@string/show_info_label"
android:src="@drawable/ic_info_white_24dp"
tools:background="@android:color/holo_green_dark"/>
tools:background="@android:color/holo_green_dark"
android:layout_marginLeft="-8dp"
android:layout_marginStart="-8dp"
android:scaleType="fitXY"
android:padding="8dp"/>
<ImageButton
android:id="@+id/butShowSettings"
@ -55,83 +80,35 @@
android:contentDescription="@string/show_feed_settings_label"
android:src="@drawable/ic_settings_white_24dp"
tools:background="@android:color/holo_green_dark"
android:layout_below="@+id/butShowInfo"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
android:scaleType="fitXY"
android:padding="8dp"/>
</LinearLayout>
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.Heading"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_toLeftOf="@id/butShowInfo"
android:layout_toStartOf="@id/butShowInfo"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
android:ellipsize="end"
android:maxLines="2"
android:shadowColor="@color/black"
android:shadowRadius="3"
android:textColor="@color/white"
tools:text="Podcast title"
tools:background="@android:color/holo_green_dark" />
</LinearLayout>
<TextView
android:id="@+id/txtvAuthor"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_below="@id/txtvTitle"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_toLeftOf="@id/butShowSettings"
android:layout_toStartOf="@id/butShowSettings"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
android:ellipsize="end"
android:lines="1"
android:shadowColor="@color/black"
android:shadowRadius="3"
android:textColor="@color/white"
android:textSize="@dimen/text_size_small"
tools:text="Podcast author"
tools:background="@android:color/holo_green_dark"/>
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvFailure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/imgvBackground"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:background="@color/download_failed_red"
android:gravity="center"
android:textColor="@color/white"
android:visibility="gone"
android:text="@string/refresh_failed_msg"
tools:text="(!) Last refresh failed"
/>
</LinearLayout>
<TextView
android:id="@+id/txtvInformation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/imgvBackground"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:gravity="center"
android:padding="2dp"
android:background="?attr/colorPrimary"
android:visibility="gone"
tools:text="(i) Information"
/>
android:gravity="center"
tools:visibility="visible"
tools:text="(i) Information"/>
</RelativeLayout>
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvFailure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:background="@color/download_failed_red"
android:gravity="center"
android:textColor="@color/white"
android:visibility="gone"
android:text="@string/refresh_failed_msg"
tools:visibility="visible"
tools:text="(!) Last refresh failed"/>
</LinearLayout>

View File

@ -3,7 +3,7 @@
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:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
@ -30,7 +30,77 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<include layout="@layout/feeditemlist_header"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/feed_image_bg">
<ImageView
android:id="@+id/imgvBackground"
style="@style/BigBlurryBackground"
android:layout_width="match_parent"
android:layout_height="@dimen/feeditemlist_header_height" />
<ImageView
android:id="@+id/imgvCover"
android:layout_width="@dimen/thumbnail_length_onlinefeedview"
android:layout_height="@dimen/thumbnail_length_onlinefeedview"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/cover_label"
tools:src="@drawable/ic_antenna"/>
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.Heading"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
android:ellipsize="end"
android:maxLines="2"
android:shadowColor="@color/black"
android:shadowRadius="3"
android:textColor="@color/white"
tools:text="Podcast title" />
<TextView
android:id="@+id/txtvAuthor"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_below="@id/txtvTitle"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_toRightOf="@id/imgvCover"
android:layout_toEndOf="@id/imgvCover"
android:ellipsize="end"
android:lines="1"
android:shadowColor="@color/black"
android:shadowRadius="3"
android:textColor="@color/white"
android:textSize="@dimen/text_size_small"
tools:text="Podcast author"/>
</RelativeLayout>
<Spinner
android:id="@+id/spinnerAlternateUrls"