more repeat modes

This commit is contained in:
Yuriy Liskov
2020-10-13 09:55:38 +03:00
parent 71072b7778
commit 041dce64fd
31 changed files with 75 additions and 324 deletions

View File

@@ -27,7 +27,6 @@ public class MainPlayerEventBridge implements PlayerEventListener {
private static MainPlayerEventBridge sInstance;
private PlaybackController mController;
private Activity mMainActivity;
private Activity mParentActivity;
public MainPlayerEventBridge() {
mEventListeners = new ArrayList<>();
@@ -36,7 +35,6 @@ public class MainPlayerEventBridge implements PlayerEventListener {
HqDialogManager hqDialogManager = new HqDialogManager();
VideoLoader videoLoader = new VideoLoader();
videoLoader.addErrorListener(uiManager);
SuggestionsLoader suggestionsLoader = new SuggestionsLoader();
suggestionsLoader.addMetadataListener(uiManager);
@@ -202,11 +200,6 @@ public class MainPlayerEventBridge implements PlayerEventListener {
process(listener -> listener.onRepeatModeClicked(modeIndex));
}
@Override
public void onRepeatModeChange(int modeIndex) {
process(listener -> listener.onRepeatModeChange(modeIndex));
}
@Override
public void onVideoLoaded(Video item) {
process(listener -> listener.onVideoLoaded(item));

View File

@@ -132,11 +132,6 @@ public abstract class PlayerEventListenerHelper implements PlayerHandlerEventLis
// NOP
}
@Override
public void onRepeatModeChange(int modeIndex) {
// NOP
}
@Override
public void onHighQualityClicked() {
// NOP

View File

@@ -17,7 +17,6 @@ public interface PlaybackEngineController {
long getLengthMs();
void setPlay(boolean play);
boolean isPlaying();
void setRepeatMode(int modeIndex);
List<FormatItem> getVideoFormats();
List<FormatItem> getAudioFormats();
List<FormatItem> getSubtitleFormats();

View File

@@ -3,6 +3,9 @@ package com.liskovsoft.smartyoutubetv2.common.app.models.playback.controller;
import com.liskovsoft.smartyoutubetv2.common.app.models.data.VideoGroup;
public interface PlaybackUiController {
int REPEAT_NONE = 0;
int REPEAT_ONE = 1;
int REPEAT_ALL = 2;
void updateSuggestions(VideoGroup group);
void resetSuggestedPosition();
void clearSuggestions();

View File

@@ -33,6 +33,5 @@ public interface PlayerEngineEventListener {
void onEngineReleased();
void onEngineError(int type);
void onPlayEnd();
void onRepeatModeChange(int modeIndex);
void onTrackChanged(FormatItem track);
}

View File

@@ -4,6 +4,9 @@ import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video;
import com.liskovsoft.smartyoutubetv2.common.autoframerate.FormatItem;
public interface PlayerUiEventListener {
int REPEAT_NONE = 0;
int REPEAT_ONE = 1;
int REPEAT_ALL = 2;
void onSuggestionItemClicked(Video item);
void onSuggestionItemLongClicked(Video item);
boolean onPreviousClicked();

View File

@@ -14,7 +14,6 @@ import com.liskovsoft.smartyoutubetv2.common.R;
import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.PlayerEventListenerHelper;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.managers.SuggestionsLoader.MetadataListener;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.managers.VideoLoader.ErrorListener;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.ui.UiOptionItem;
import com.liskovsoft.smartyoutubetv2.common.app.presenters.AppSettingsPresenter;
import com.liskovsoft.smartyoutubetv2.common.app.presenters.ChannelPresenter;
@@ -25,7 +24,7 @@ import io.reactivex.schedulers.Schedulers;
import java.util.List;
public class PlayerUiManager extends PlayerEventListenerHelper implements MetadataListener, ErrorListener {
public class PlayerUiManager extends PlayerEventListenerHelper implements MetadataListener {
private static final String TAG = PlayerUiManager.class.getSimpleName();
private static final long UI_AUTO_HIDE_TIMEOUT_MS = 3_000;
private static final long SUGGESTIONS_RESET_TIMEOUT_MS = 500;
@@ -125,15 +124,10 @@ public class PlayerUiManager extends PlayerEventListenerHelper implements Metada
disposeTimeouts();
}
@Override
public void onRepeatModeClicked(int modeIndex) {
mController.setRepeatMode(modeIndex);
}
@Override
public void onRepeatModeChange(int modeIndex) {
mController.setRepeatButtonState(modeIndex);
}
//@Override
//public void onRepeatModeClicked(int modeIndex) {
// //mController.setRepeatMode(modeIndex);
//}
@Override
public void onMetadata(MediaItemMetadata metadata) {
@@ -221,9 +215,4 @@ public class PlayerUiManager extends PlayerEventListenerHelper implements Metada
private interface MediaItemObservable {
Observable<Void> call(MediaItem item);
}
@Override
public void onError(int type) {
mController.showControls(true);
}
}

View File

@@ -18,7 +18,6 @@ import java.util.Map;
public class StateUpdater extends PlayerEventListenerHelper {
private boolean mIsPlaying;
private int mRepeatMode = 0;
private FormatItem mVideoFormat;
private FormatItem mAudioFormat;
private FormatItem mSubtitleFormat;
@@ -63,7 +62,7 @@ public class StateUpdater extends PlayerEventListenerHelper {
*/
@Override
public void openVideo(Video item) {
mLastSpeed = -1; // Save global speed on per-view basis
//mLastSpeed = -1; // Save global speed on per-view basis
ensureVideoSize(item); // reset position of music videos
@@ -101,11 +100,6 @@ public class StateUpdater extends PlayerEventListenerHelper {
saveState();
}
@Override
public void onEngineInitialized() {
mController.setRepeatMode(mRepeatMode);
}
@Override
public void onEngineReleased() {
saveState();
@@ -139,11 +133,6 @@ public class StateUpdater extends PlayerEventListenerHelper {
Helpers.enableScreensaver(mActivity);
}
@Override
public void onRepeatModeChange(int modeIndex) {
mRepeatMode = modeIndex;
}
@Override
public void onTrackSelected(FormatItem track) {
if (track.getType() == FormatItem.TYPE_VIDEO && !mController.isInPIPMode()) {

View File

@@ -1,5 +1,6 @@
package com.liskovsoft.smartyoutubetv2.common.app.models.playback.managers;
import android.app.Activity;
import com.liskovsoft.mediaserviceinterfaces.MediaItemManager;
import com.liskovsoft.mediaserviceinterfaces.MediaService;
import com.liskovsoft.mediaserviceinterfaces.data.MediaItem;
@@ -9,17 +10,16 @@ import com.liskovsoft.sharedutils.mylogger.Log;
import com.liskovsoft.smartyoutubetv2.common.app.models.data.Playlist;
import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.PlayerEventListenerHelper;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.controller.PlaybackUiController;
import com.liskovsoft.smartyoutubetv2.common.app.models.playback.managers.SuggestionsLoader.MetadataListener;
import com.liskovsoft.smartyoutubetv2.common.app.presenters.ChannelPresenter;
import com.liskovsoft.smartyoutubetv2.common.autoframerate.FormatItem;
import com.liskovsoft.smartyoutubetv2.common.prefs.AppPrefs;
import com.liskovsoft.youtubeapi.service.YouTubeMediaService;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.List;
public class VideoLoader extends PlayerEventListenerHelper implements MetadataListener {
private static final String TAG = VideoLoader.class.getSimpleName();
private final Playlist mPlaylist;
@@ -29,17 +29,19 @@ public class VideoLoader extends PlayerEventListenerHelper implements MetadataLi
private Disposable mFormatInfoAction;
private boolean mEngineInitialized;
private MediaItem mCachedNextVideo;
private final List<ErrorListener> mListeners = new ArrayList<>();
public interface ErrorListener {
int TYPE_EMPTY_SOURCE = 0;
void onError(int type);
}
private int mRepeatMode = PlaybackUiController.REPEAT_ALL;
public VideoLoader() {
mPlaylist = Playlist.instance();
}
@Override
public void onActivity(Activity activity) {
super.onActivity(activity);
mRepeatMode = AppPrefs.instance(activity).getVideoLoaderData(PlaybackUiController.REPEAT_ALL);
}
@Override
public void openVideo(Video item) {
mPlaylist.add(item);
@@ -57,6 +59,7 @@ public class VideoLoader extends PlayerEventListenerHelper implements MetadataLi
public void onEngineInitialized() {
mEngineInitialized = true;
loadVideo(mLastVideo);
mController.setRepeatButtonState(mRepeatMode);
}
@Override
@@ -110,7 +113,17 @@ public class VideoLoader extends PlayerEventListenerHelper implements MetadataLi
@Override
public void onPlayEnd() {
onNextClicked();
switch (mRepeatMode) {
case PlaybackUiController.REPEAT_ALL:
onNextClicked();
break;
case PlaybackUiController.REPEAT_ONE:
loadVideo(mLastVideo);
break;
default: // none
mController.showControls(true);
break;
}
}
@Override
@@ -131,6 +144,12 @@ public class VideoLoader extends PlayerEventListenerHelper implements MetadataLi
mCachedNextVideo = metadata.getNextVideo();
}
@Override
public void onRepeatModeClicked(int modeIndex) {
mRepeatMode = modeIndex;
AppPrefs.instance(mActivity).setVideoLoaderData(mRepeatMode);
}
private void disposeActions() {
if (mMetadataAction != null && !mMetadataAction.isDisposed()) {
mMetadataAction.dispose();
@@ -205,17 +224,7 @@ public class VideoLoader extends PlayerEventListenerHelper implements MetadataLi
mController.openUrlList(formatInfo.createUrlList());
} else {
Log.e(TAG, "Empty format info received. No video data to pass to the player.");
callListener(ErrorListener.TYPE_EMPTY_SOURCE);
}
}
public void addErrorListener(ErrorListener listener) {
mListeners.add(listener);
}
private void callListener(int type) {
for (ErrorListener listener : mListeners) {
listener.onError(type);
mController.showControls(true);
}
}
}

View File

@@ -122,12 +122,6 @@ public class ExoPlayerController implements Player.EventListener, PlayerControll
return mVideo;
}
@Override
public void setRepeatMode(int modeIndex) {
mPlayer.setRepeatMode(modeIndex);
mEventListener.onRepeatModeChange(modeIndex);
}
@Override
public List<FormatItem> getVideoFormats() {
return ExoFormatItem.from(mTrackSelectorManager.getVideoTracks());

View File

@@ -63,11 +63,6 @@ public class NullPlayerController implements PlayerController {
return null;
}
@Override
public void setRepeatMode(int modeIndex) {
}
@Override
public List<FormatItem> getVideoFormats() {
return null;

View File

@@ -24,7 +24,6 @@ public interface PlayerController {
void setEventListener(PlayerEventListener eventListener);
void setVideo(Video video);
Video getVideo();
void setRepeatMode(int modeIndex);
List<FormatItem> getVideoFormats();
List<FormatItem> getAudioFormats();
List<FormatItem> getSubtitleFormats();

View File

@@ -15,6 +15,7 @@ public class AppPrefs extends SharedPreferencesBase {
private static final String VIDEO_BUFFER_TYPE = "video_buffer_type";
private static final String AUTO_FRAME_RATE_DATA = "auto_frame_rate_data";
private static final String BACKUP_DATA = "backup_data";
private static final String VIDEO_LOADER_DATA = "video_loader_data";
private String mDefaultDisplayMode;
private String mCurrentDisplayMode;
@@ -86,4 +87,12 @@ public class AppPrefs extends SharedPreferencesBase {
public String getBackupData() {
return getString(BACKUP_DATA, null);
}
public int getVideoLoaderData(int defaultVal) {
return getInt(VIDEO_LOADER_DATA, defaultVal);
}
public void setVideoLoaderData(int data) {
putInt(VIDEO_LOADER_DATA, data);
}
}

View File

@@ -181,22 +181,6 @@
android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>
<receiver
android:name=".old.recommendation.RecommendationReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".old.data.FetchVideoService"
android:exported="false" />
<service
android:name=".old.recommendation.UpdateRecommendationsService"
android:enabled="true" />
<activity android:name="com.liskovsoft.smartyoutubetv2.tv.old.ui.SettingsActivity"
android:exported="true"
android:screenOrientation="landscape"

View File

@@ -1,46 +0,0 @@
/*
* Copyright (c) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.liskovsoft.smartyoutubetv2.tv.old.recommendation;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/*
* This class extends BroadcastReceiver and publishes Recommendations when received.
*/
public class RecommendationReceiver extends BroadcastReceiver {
private static final long INITIAL_DELAY = 5000;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
scheduleRecommendationUpdate(context);
}
}
private void scheduleRecommendationUpdate(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent recommendationIntent = new Intent(context, UpdateRecommendationsService.class);
PendingIntent alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, INITIAL_DELAY,
AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
}
}

View File

@@ -1,140 +0,0 @@
/*
* Copyright (c) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.liskovsoft.smartyoutubetv2.tv.old.recommendation;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Build.VERSION;
import android.preference.PreferenceManager;
import androidx.recommendation.app.ContentRecommendation;
import android.util.Log;
import com.bumptech.glide.Glide;
import com.liskovsoft.smartyoutubetv2.tv.BuildConfig;
import com.liskovsoft.smartyoutubetv2.tv.R;
import com.liskovsoft.smartyoutubetv2.tv.old.data.VideoContract;
import com.liskovsoft.smartyoutubetv2.common.app.models.data.Video;
import com.liskovsoft.smartyoutubetv2.tv.old.model.VideoCursorMapper;
import com.liskovsoft.smartyoutubetv2.tv.ui.details.VideoDetailsActivity;
import java.util.concurrent.ExecutionException;
/*
* This class builds up to MAX_RECOMMENDATIONS of ContentRecommendations and defines what happens
* when they're selected from Recommendations section on the Home screen by creating an Intent.
*/
public class UpdateRecommendationsService extends IntentService {
private static final String TAG = "RecommendationService";
private static final int MAX_RECOMMENDATIONS = 3;
private static final VideoCursorMapper mVideoCursorMapper = new VideoCursorMapper();
private NotificationManager mNotifManager;
public UpdateRecommendationsService() {
super(TAG);
}
@Override
public void onCreate() {
super.onCreate();
if (mNotifManager == null) {
mNotifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
}
@Override
protected void onHandleIntent(Intent intent) {
if (VERSION.SDK_INT < 21) {
Log.d(TAG, "Recommendations are not supported on api < 21");
mNotifManager.cancelAll();
return;
}
// Generate recommendations, but only if recommendations are enabled
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!sharedPreferences.getBoolean(getString(R.string.pref_key_recommendations), true)) {
Log.d(TAG, "Recommendations disabled in preferences");
mNotifManager.cancelAll();
return;
}
Resources res = getResources();
int cardWidth = res.getDimensionPixelSize(R.dimen.card_width);
int cardHeight = res.getDimensionPixelSize(R.dimen.card_height);
ContentRecommendation.Builder builder = new ContentRecommendation.Builder()
.setBadgeIcon(R.drawable.videos_by_google_icon);
Cursor cursor = getContentResolver().query(
VideoContract.VideoEntry.CONTENT_URI,
null, // projection
null, // selection
null, // selection clause
"RANDOM() LIMIT " + MAX_RECOMMENDATIONS // sort order
);
if (cursor != null && cursor.moveToNext()) {
try {
do {
Video video = (Video) mVideoCursorMapper.convert(cursor);
int id = Long.valueOf(video.id).hashCode();
builder.setIdTag("Video" + id)
.setTitle(video.title)
.setText(getString(R.string.popular_header))
.setContentIntentData(ContentRecommendation.INTENT_TYPE_ACTIVITY,
buildPendingIntent(video, id), 0, null);
Bitmap bitmap = Glide.with(getApplication())
.asBitmap()
.load(video.cardImageUrl)
.submit(cardWidth, cardHeight) // Only use for synchronous .get()
.get();
builder.setContentImage(bitmap);
// Create an object holding all the information used to recommend the content.
ContentRecommendation rec = builder.build();
Notification notification = rec.getNotificationObject(getApplicationContext());
if (BuildConfig.DEBUG) Log.d(TAG, "Recommending video " + video.title);
// Recommend the content by publishing the notification.
mNotifManager.notify(id, notification);
} while (cursor.moveToNext());
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "Could not create recommendation.", e);
} finally {
cursor.close();
}
}
}
private Intent buildPendingIntent(Video video, int id) {
Intent detailsIntent = new Intent(this, VideoDetailsActivity.class);
detailsIntent.putExtra(VideoDetailsActivity.VIDEO, video);
detailsIntent.putExtra(VideoDetailsActivity.NOTIFICATION_ID, id);
detailsIntent.setAction(Long.toString(video.id));
return detailsIntent;
}
}

View File

@@ -400,10 +400,11 @@ public class PlaybackTransportRowPresenter extends PlaybackRowPresenter {
} else {
mPositionsLength = 0;
}
mControlsVh.view.setVisibility(View.GONE);
mSecondaryControlsVh.view.setVisibility(View.INVISIBLE);
mDescriptionViewHolder.view.setVisibility(View.INVISIBLE);
mThumbsBar.setVisibility(View.VISIBLE);
// MOD: seek ui tweaks
//mControlsVh.view.setVisibility(View.GONE);
//mSecondaryControlsVh.view.setVisibility(View.INVISIBLE);
//mDescriptionViewHolder.view.setVisibility(View.INVISIBLE);
//mThumbsBar.setVisibility(View.VISIBLE);
return true;
}

View File

@@ -446,11 +446,6 @@ public class PlaybackFragment extends VideoSupportFragment implements PlaybackVi
return mExoPlayerController.isPlaying();
}
@Override
public void setRepeatMode(int modeIndex) {
mExoPlayerController.setRepeatMode(modeIndex);
}
@Override
public List<FormatItem> getVideoFormats() {
return mExoPlayerController.getVideoFormats();

View File

@@ -101,8 +101,8 @@ public class VideoPlayerGlue extends MaxIconNumVideoPlayerGlue<PlayerAdapter> {
// > /|| |< << >> >|
super.onCreatePrimaryActions(adapter);
adapter.add(mSkipPreviousAction);
adapter.add(mRewindAction);
adapter.add(mFastForwardAction);
//adapter.add(mRewindAction);
//adapter.add(mFastForwardAction);
adapter.add(mSkipNextAction);
adapter.add(mRepeatAction);
adapter.add(mVideoSpeedAction);

View File

@@ -10,15 +10,11 @@ import com.liskovsoft.smartyoutubetv2.tv.R;
* An action for displaying two repeat states: none and all.
*/
public class RepeatAction extends MultiAction {
/**
* Action index for the repeat-none icon.
*/
public static final int INDEX_NONE = 0;
public static final int INDEX_ONE = 1;
/**
* Action index for the repeat-all icon.
*/
public static final int INDEX_ALL = 1;
public static final int INDEX_ALL = 2;
/**
* Constructor
@@ -35,20 +31,24 @@ public class RepeatAction extends MultiAction {
*/
public RepeatAction(Context context, int selectionColor) {
super(R.id.lb_control_repeat);
Drawable[] drawables = new Drawable[2];
Drawable[] drawables = new Drawable[3];
BitmapDrawable repeatDrawable = (BitmapDrawable) ActionHelpers.getStyledDrawable(context,
R.styleable.lbPlaybackControlsActionIcons_repeat);
BitmapDrawable repeatOneDrawable = (BitmapDrawable) ActionHelpers.getStyledDrawable(context,
R.styleable.lbPlaybackControlsActionIcons_repeat_one);
drawables[INDEX_NONE] = repeatDrawable;
drawables[INDEX_ALL] = repeatOneDrawable == null ? null
drawables[INDEX_ONE] = repeatOneDrawable == null ? null
: new BitmapDrawable(context.getResources(),
ActionHelpers.createBitmap(repeatOneDrawable.getBitmap(), selectionColor));
drawables[INDEX_ALL] = repeatDrawable == null ? null
: new BitmapDrawable(context.getResources(),
ActionHelpers.createBitmap(repeatDrawable.getBitmap(), selectionColor));
setDrawables(drawables);
String[] labels = new String[drawables.length];
// Note, labels denote the action taken when clicked
labels[INDEX_NONE] = context.getString(R.string.lb_playback_controls_repeat_none);
labels[INDEX_ONE] = context.getString(R.string.lb_playback_controls_repeat_one);
labels[INDEX_ALL] = context.getString(R.string.lb_playback_controls_repeat_all);
setLabels(labels);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 160dpi, Red Box TV, Eltex, same as hdpi -->
<dimen name="card_width">286dp</dimen>
<dimen name="card_height">165dp</dimen>
<!-- Elements below aren't used in the app -->
<dimen name="grid_item_width">130dp</dimen>
<dimen name="grid_item_height">130dp</dimen>
<dimen name="spinner_width">65dp</dimen>
<dimen name="spinner_height">65dp</dimen>
<dimen name="detail_thumb_width">355dp</dimen>
<dimen name="detail_thumb_height">355dp</dimen>
<dimen name="playback_overlay_width">310dp</dimen>
<dimen name="playback_overlay_height">310dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">20dp</dimen>
<dimen name="activity_vertical_margin">20dp</dimen>
</resources>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 4K TV with 280dpi, same as w1097 -->
<!-- 1080p TV with 240dpi -->
<!-- Example: width in dp = width in pixle / (dpi/160) dp = 1440/(560/160) =~ 411 -->
<!-- Create drawable-w411dp -->
<dimen name="card_width">231dp</dimen>
<dimen name="card_height">133dp</dimen>
<dimen name="card_width">286dp</dimen>
<dimen name="card_height">165dp</dimen>
<!-- Elements below aren't used in the app -->

View File

@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 240dpi, Vermax 300UHD, xhdpi * 1.3 -->
<!-- 1080p TV with 160dpi -->
<!-- 160dpi, Red Box TV, Eltex, same as 240dpi -->
<!-- Example: width in dp = width in pixle / (dpi/160) dp = 1440/(560/160) =~ 411 -->
<!-- Create drawable-w411dp -->
<dimen name="card_width">286dp</dimen>
<dimen name="card_height">165dp</dimen>