1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-11-16 23:04:56 +00:00

improved fling behavior, added tab indicator dots, added next video in related videos

This commit is contained in:
Ritvik Saraf 2018-10-17 00:23:02 +05:30
parent cf3e53eb71
commit 9fc38b5bb8
14 changed files with 313 additions and 59 deletions

View File

@ -0,0 +1,143 @@
package android.support.design.widget;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
// check this https://github.com/ToDou/appbarlayout-spring-behavior/blob/master/appbarspring/src/main/java/android/support/design/widget/AppBarFlingFixBehavior.java
public final class FlingBehavior extends AppBarLayout.Behavior {
private ValueAnimator mOffsetAnimator;
private static final int MAX_OFFSET_ANIMATION_DURATION = 600; // ms
public FlingBehavior() {
}
public FlingBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
if (dy != 0) {
int val = child.getBottom();
if (val != 0) {
int min, max;
if (dy < 0) {
// We're scrolling down
} else {
// We're scrolling up
min = -child.getUpNestedPreScrollRange();
max = 0;
consumed[1] = scroll(coordinatorLayout, child, dy, min, max);
}
}
}
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, View target, int type) {
super.onStopNestedScroll(coordinatorLayout, abl, target, type);
}
@Override
public boolean onMeasureChild(CoordinatorLayout parent, AppBarLayout child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
return super.onMeasureChild(parent, child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
}
@Override
public Parcelable onSaveInstanceState(CoordinatorLayout parent, AppBarLayout abl) {
return super.onSaveInstanceState(parent, abl);
}
@Override
public void onRestoreInstanceState(CoordinatorLayout parent, AppBarLayout appBarLayout, Parcelable state) {
super.onRestoreInstanceState(parent, appBarLayout, state);
}
@Override
public boolean onNestedPreFling(@NonNull CoordinatorLayout coordinatorLayout, @NonNull AppBarLayout child, @NonNull View target, float velocityX, float velocityY) {
if (velocityY != 0) {
if (velocityY < 0) {
// We're flinging down
int val = child.getBottom();
if (val != 0) {
final int targetScroll =
+child.getDownNestedPreScrollRange();
animateOffsetTo(coordinatorLayout, child, targetScroll, velocityY);
}
} else {
// We're flinging up
int val = child.getBottom();
if (val != 0) {
final int targetScroll = -child.getUpNestedPreScrollRange();
if (getTopBottomOffsetForScrollingSibling() > targetScroll) {
animateOffsetTo(coordinatorLayout, child, targetScroll, velocityY);
}
}
}
}
return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);
}
private void animateOffsetTo(final CoordinatorLayout coordinatorLayout,
final AppBarLayout child, final int offset, float velocity) {
final int distance = Math.abs(getTopBottomOffsetForScrollingSibling() - offset);
final int duration;
velocity = Math.abs(velocity);
if (velocity > 0) {
duration = 3 * Math.round(1000 * (distance / velocity));
} else {
final float distanceRatio = (float) distance / child.getHeight();
duration = (int) ((distanceRatio + 1) * 150);
}
animateOffsetWithDuration(coordinatorLayout, child, offset, duration);
}
private void animateOffsetWithDuration(final CoordinatorLayout coordinatorLayout,
final AppBarLayout child, final int offset, final int duration) {
final int currentOffset = getTopBottomOffsetForScrollingSibling();
if (currentOffset == offset) {
if (mOffsetAnimator != null && mOffsetAnimator.isRunning()) {
mOffsetAnimator.cancel();
}
return;
}
if (mOffsetAnimator == null) {
mOffsetAnimator = new ValueAnimator();
mOffsetAnimator.setInterpolator(AnimationUtils.DECELERATE_INTERPOLATOR);
mOffsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
setHeaderTopBottomOffset(coordinatorLayout, child,
(Integer) animator.getAnimatedValue());
}
});
} else {
mOffsetAnimator.cancel();
}
mOffsetAnimator.setDuration(Math.min(duration, MAX_OFFSET_ANIMATION_DURATION));
mOffsetAnimator.setIntValues(currentOffset, offset);
mOffsetAnimator.start();
}
}

View File

@ -1,10 +1,8 @@
package org.schabi.newpipe.fragments.detail; package org.schabi.newpipe.fragments.detail;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -29,12 +27,6 @@ public class TabAdaptor extends FragmentPagerAdapter {
return mFragmentList.size(); return mFragmentList.size();
} }
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
// give an ID different from position when position has been changed // give an ID different from position when position has been changed

View File

@ -29,7 +29,6 @@ import android.text.method.LinkMovementMethod;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -39,7 +38,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
@ -56,8 +54,6 @@ import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.download.DownloadDialog; import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.comments.CommentsInfo;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
@ -72,7 +68,6 @@ import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.fragments.list.comments.CommentsFragment; import org.schabi.newpipe.fragments.list.comments.CommentsFragment;
import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment; import org.schabi.newpipe.fragments.list.videos.RelatedVideosFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
@ -91,11 +86,9 @@ import org.schabi.newpipe.util.InfoCache;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.StreamItemAdapter; import org.schabi.newpipe.util.StreamItemAdapter;
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper; import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
@ -964,24 +957,6 @@ public class VideoDetailFragment
})); }));
} }
private View getSeparatorView() {
View separator = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
int m8 = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
int m5 = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
params.setMargins(m8, m5, m8, m5);
separator.setLayoutParams(params);
TypedValue typedValue = new TypedValue();
activity.getTheme().resolveAttribute(R.attr.separator_color, typedValue, true);
separator.setBackgroundColor(typedValue.data);
return separator;
}
private void setHeightThumbnail() { private void setHeightThumbnail() {
final DisplayMetrics metrics = getResources().getDisplayMetrics(); final DisplayMetrics metrics = getResources().getDisplayMetrics();
boolean isPortrait = metrics.heightPixels > metrics.widthPixels; boolean isPortrait = metrics.heightPixels > metrics.widthPixels;

View File

@ -22,9 +22,9 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.info_list.InfoListAdapter; import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;

View File

@ -1,7 +1,9 @@
package org.schabi.newpipe.fragments.list.videos; package org.schabi.newpipe.fragments.list.videos;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -9,34 +11,31 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.comments.CommentsInfo;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.RelatedStreamInfo; import org.schabi.newpipe.util.RelatedStreamInfo;
import java.util.List; import java.io.Serializable;
import io.reactivex.Single; import io.reactivex.Single;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInfo> { public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInfo> implements SharedPreferences.OnSharedPreferenceChangeListener{
private CompositeDisposable disposables = new CompositeDisposable(); private CompositeDisposable disposables = new CompositeDisposable();
private RelatedStreamInfo relatedStreamInfo; private RelatedStreamInfo relatedStreamInfo;
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Views // Views
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private View headerRootLayout;
private Switch aSwitch;
@ -74,6 +73,28 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
if (disposables != null) disposables.clear(); if (disposables != null) disposables.clear();
} }
protected View getListHeader(){
if(relatedStreamInfo != null && relatedStreamInfo.getNextStream() != null){
headerRootLayout = activity.getLayoutInflater().inflate(R.layout.related_streams_header, itemsList, false);
aSwitch = headerRootLayout.findViewById(R.id.autoplay_switch);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
Boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
aSwitch.setChecked(autoplay);
aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
prefEdit.putBoolean(getString(R.string.auto_queue_key), b);
prefEdit.apply();
}
});
return headerRootLayout;
}else{
return null;
}
}
@Override @Override
protected Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() { protected Single<ListExtractor.InfoItemsPage> loadMoreItemsLogic() {
return Single.fromCallable(() -> ListExtractor.InfoItemsPage.emptyPage()); return Single.fromCallable(() -> ListExtractor.InfoItemsPage.emptyPage());
@ -145,6 +166,33 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
private void setInitialData(StreamInfo info) { private void setInitialData(StreamInfo info) {
super.setInitialData(info.getServiceId(), info.getUrl(), info.getName()); super.setInitialData(info.getServiceId(), info.getUrl(), info.getName());
this.relatedStreamInfo = RelatedStreamInfo.getInfo(info); if(this.relatedStreamInfo == null) this.relatedStreamInfo = RelatedStreamInfo.getInfo(info);
}
private static final String INFO_KEY = "related_info_key";
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(INFO_KEY, relatedStreamInfo);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedState) {
super.onRestoreInstanceState(savedState);
if (savedState != null) {
Serializable serializable = savedState.getSerializable(INFO_KEY);
if(serializable instanceof RelatedStreamInfo){
this.relatedStreamInfo = (RelatedStreamInfo) serializable;
}
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
Boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
aSwitch.setChecked(autoplay);
} }
} }

View File

@ -4,11 +4,15 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListInfo; import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
public class RelatedStreamInfo extends ListInfo<InfoItem> { public class RelatedStreamInfo extends ListInfo<InfoItem> {
private StreamInfoItem nextStream;
public RelatedStreamInfo(int serviceId, ListLinkHandler listUrlIdHandler, String name) { public RelatedStreamInfo(int serviceId, ListLinkHandler listUrlIdHandler, String name) {
super(serviceId, listUrlIdHandler, name); super(serviceId, listUrlIdHandler, name);
@ -17,7 +21,21 @@ public class RelatedStreamInfo extends ListInfo<InfoItem> {
public static RelatedStreamInfo getInfo(StreamInfo info) { public static RelatedStreamInfo getInfo(StreamInfo info) {
ListLinkHandler handler = new ListLinkHandler(info.getOriginalUrl(), info.getUrl(), info.getId(), Collections.emptyList(), null); ListLinkHandler handler = new ListLinkHandler(info.getOriginalUrl(), info.getUrl(), info.getId(), Collections.emptyList(), null);
RelatedStreamInfo relatedStreamInfo = new RelatedStreamInfo(info.getServiceId(), handler, info.getName()); RelatedStreamInfo relatedStreamInfo = new RelatedStreamInfo(info.getServiceId(), handler, info.getName());
relatedStreamInfo.setRelatedItems(info.getRelatedStreams()); List<InfoItem> streams = new ArrayList<>();
if(info.getNextVideo() != null){
streams.add(info.getNextVideo());
}
streams.addAll(info.getRelatedStreams());
relatedStreamInfo.setRelatedItems(streams);
relatedStreamInfo.setNextStream(info.getNextVideo());
return relatedStreamInfo; return relatedStreamInfo;
} }
public StreamInfoItem getNextStream() {
return nextStream;
}
public void setNextStream(StreamInfoItem nextStream) {
this.nextStream = nextStream;
}
} }

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="6dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_dot"/>
</selector>

View File

@ -65,6 +65,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="4dp"
android:background="?attr/toolbar_shadow_drawable" android:background="?attr/toolbar_shadow_drawable"
android:layout_alignParentTop="true"/> android:layout_alignParentTop="true"
android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>

View File

@ -65,6 +65,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="4dp"
android:background="?attr/toolbar_shadow_drawable" android:background="?attr/toolbar_shadow_drawable"
android:layout_alignParentTop="true"/> android:layout_alignParentTop="true"
android:visibility="gone"/>
</RelativeLayout> </RelativeLayout>

View File

@ -10,12 +10,16 @@
<android.support.design.widget.CoordinatorLayout <android.support.design.widget.CoordinatorLayout
android:id="@+id/detail_main_content" android:id="@+id/detail_main_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:id="@+id/appbarlayout" android:id="@+id/appbarlayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:elevation="0dp"
app:layout_behavior="android.support.design.widget.FlingBehavior">
<android.support.design.widget.CollapsingToolbarLayout <android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -458,21 +462,27 @@
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="?android:windowBackground">
</android.support.design.widget.TabLayout>
</android.support.design.widget.AppBarLayout> </android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager <android.support.v4.view.ViewPager
android:id="@+id/viewpager" android:id="@+id/viewpager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:background="@color/transparent_background_color"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp">
</android.support.design.widget.TabLayout>
</android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>
</FrameLayout> </FrameLayout>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/channel_header_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground">
<TextView
android:id="@+id/next_stream_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="5dp"
android:text="@string/next_video_title"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp"
tools:ignore="RtlHardcoded" />
<Switch
android:id="@+id/autoplay_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:paddingRight="5dp"
android:switchPadding="5dp"
android:textSize="12sp"
android:textColor="@android:color/tab_indicator_text"
android:text="@string/autoplay_title" />
</RelativeLayout>

View File

@ -95,7 +95,8 @@
<string name="resume_on_audio_focus_gain_title">Resume on focus gain</string> <string name="resume_on_audio_focus_gain_title">Resume on focus gain</string>
<string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phone calls)</string> <string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phone calls)</string>
<string name="download_dialog_title">Download</string> <string name="download_dialog_title">Download</string>
<string name="next_video_title">Next video</string> <string name="next_video_title">Up next</string>
<string name="autoplay_title">Autoplay</string>
<string name="show_next_and_similar_title">Show \'next\' and \'similar\' videos</string> <string name="show_next_and_similar_title">Show \'next\' and \'similar\' videos</string>
<string name="show_hold_to_append_title">Show \"hold to append\" tip</string> <string name="show_hold_to_append_title">Show \"hold to append\" tip</string>
<string name="show_hold_to_append_summary">Show tip when background or popup button is pressed on video details page</string> <string name="show_hold_to_append_summary">Show tip when background or popup button is pressed on video details page</string>