diff --git a/app/build.gradle b/app/build.gradle index 753b4fd..3b85641 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -115,7 +115,6 @@ dependencies { compile "com.android.support:cardview-v7:${supportLibVersion}" compile "com.android.support:preference-v14:${supportLibVersion}" compile "com.android.support:support-v13:${supportLibVersion}" - compile "com.android.support:gridlayout-v7:${supportLibVersion}" compile 'com.fasterxml.jackson.core:jackson-databind:2.5.2' compile 'com.jakewharton:butterknife:6.1.0' diff --git a/app/src/main/java/org/xbmc/kore/ui/sections/remote/RemoteFragment.java b/app/src/main/java/org/xbmc/kore/ui/sections/remote/RemoteFragment.java index 7d23886..a5f6c1d 100644 --- a/app/src/main/java/org/xbmc/kore/ui/sections/remote/RemoteFragment.java +++ b/app/src/main/java/org/xbmc/kore/ui/sections/remote/RemoteFragment.java @@ -15,14 +15,24 @@ */ package org.xbmc.kore.ui.sections.remote; +import android.annotation.TargetApi; +import android.content.res.ColorStateList; +import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.BitmapFactory; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; @@ -46,8 +56,8 @@ import org.xbmc.kore.jsonrpc.method.Player; import org.xbmc.kore.jsonrpc.type.GlobalType; import org.xbmc.kore.jsonrpc.type.ListType; import org.xbmc.kore.jsonrpc.type.PlayerType; -import org.xbmc.kore.ui.widgets.ControlPad; import org.xbmc.kore.utils.LogUtils; +import org.xbmc.kore.utils.RepeatListener; import org.xbmc.kore.utils.UIUtils; import org.xbmc.kore.utils.Utils; @@ -64,8 +74,7 @@ import butterknife.Optional; * Remote view */ public class RemoteFragment extends Fragment - implements HostConnectionObserver.PlayerEventsObserver, - ControlPad.OnPadButtonsListener { + implements HostConnectionObserver.PlayerEventsObserver { private static final String TAG = LogUtils.makeLogTag(RemoteFragment.class); /** @@ -93,35 +102,9 @@ public class RemoteFragment extends Fragment */ private String currentNowPlayingItemType = null; - private final Packet leftButtonPacket = - new PacketBUTTON(ButtonCodes.MAP_REMOTE, ButtonCodes.REMOTE_LEFT, false, true, - true, (short)0, (byte)0); - private final Packet rightButtonPacket = - new PacketBUTTON(ButtonCodes.MAP_REMOTE, ButtonCodes.REMOTE_RIGHT, false, true, - true, (short)0, (byte)0); - private final Packet upButtonPacket = - new PacketBUTTON(ButtonCodes.MAP_REMOTE, ButtonCodes.REMOTE_UP, false, true, - true, (short)0, (byte)0); - private final Packet downButtonPacket = - new PacketBUTTON(ButtonCodes.MAP_REMOTE, ButtonCodes.REMOTE_DOWN, false, true, - true, (short)0, (byte)0); - private final Packet selectButtonPack = - new PacketBUTTON(ButtonCodes.MAP_REMOTE, ButtonCodes.REMOTE_SELECT, false, true, - true, (short)0, (byte)0); - - private final ApiMethod downButtonAction = new Input.Down(); - private final ApiMethod leftButtonAction = new Input.Left(); - private final ApiMethod upButtonAction = new Input.Up(); - private final ApiMethod rightButtonAction = new Input.Right(); - private final ApiMethod selectButtonAction = new Input.Select(); - private final ApiMethod backButtonAction = new Input.Back(); - private final ApiMethod infoButtonAction = new Input.ExecuteAction(Input.ExecuteAction.INFO); - private final ApiMethod contextButtonAction = new Input.ExecuteAction(Input.ExecuteAction.CONTEXTMENU); - private final ApiMethod osdButtonAction = new Input.ExecuteAction(Input.ExecuteAction.OSD); - @InjectView(R.id.info_panel) RelativeLayout infoPanel; @InjectView(R.id.media_panel) RelativeLayout mediaPanel; - @InjectView(R.id.remote) ControlPad controlPad; + @InjectView(R.id.remote) RelativeLayout remotePanel; @InjectView(R.id.info_title) TextView infoTitle; @InjectView(R.id.info_message) TextView infoMessage; @@ -143,6 +126,16 @@ public class RemoteFragment extends Fragment @Optional @InjectView(R.id.weather) ImageButton weatherButton; @Optional @InjectView(R.id.system) ImageButton systemButton; + @InjectView(R.id.select) ImageView selectButton; + @InjectView(R.id.left) ImageView leftButton; + @InjectView(R.id.right) ImageView rightButton; + @InjectView(R.id.up) ImageView upButton; + @InjectView(R.id.down) ImageView downButton; + @InjectView(R.id.back) ImageView backButton; + @InjectView(R.id.info) ImageView infoButton; + @InjectView(R.id.context) ImageView contextButton; + @InjectView(R.id.osd) ImageView osdButton; + @InjectView(R.id.art) ImageView thumbnail; @InjectView(R.id.title) TextView nowPlayingTitle; @InjectView(R.id.details) TextView nowPlayingDetails; @@ -152,6 +145,11 @@ public class RemoteFragment extends Fragment @InjectView(R.id.rewind) ImageButton rewindButton; @InjectView(R.id.fast_forward) ImageButton fastForwardButton; + private Animation buttonInAnim; + private Animation buttonOutAnim; + // Touch listener that provides touch feedback + private View.OnTouchListener feedbackTouchListener; + // EventServer connection private EventServerConnection eventServerConnection = null; @@ -164,7 +162,27 @@ public class RemoteFragment extends Fragment hostManager = HostManager.getInstance(getActivity()); hostConnectionObserver = hostManager.getHostConnectionObserver(); + buttonInAnim = AnimationUtils.loadAnimation(getActivity(), R.anim.button_in); + buttonOutAnim = AnimationUtils.loadAnimation(getActivity(), R.anim.button_out); + createEventServerConnection(); + + feedbackTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + buttonInAnim.setFillAfter(true); + v.startAnimation(buttonInAnim); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + v.startAnimation(buttonOutAnim); + break; + } + return false; + } + }; } @Override @@ -172,9 +190,43 @@ public class RemoteFragment extends Fragment ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_remote, container, false); ButterKnife.inject(this, root); - controlPad.setOnPadButtonsListener(this); + if (hostManager.getHostInfo().getUseEventServer() && + (eventServerConnection != null)) { + // Setup d-pad to use EventServer + setupEventServerButton(leftButton, ButtonCodes.REMOTE_LEFT); + setupEventServerButton(rightButton, ButtonCodes.REMOTE_RIGHT); + setupEventServerButton(upButton, ButtonCodes.REMOTE_UP); + setupEventServerButton(downButton, ButtonCodes.REMOTE_DOWN); + setupEventServerButton(selectButton, ButtonCodes.REMOTE_SELECT); + } else { + // Otherwise, use json-rpc + setupRepeatButton(leftButton, new Input.Left()); + setupRepeatButton(rightButton, new Input.Right()); + setupRepeatButton(upButton, new Input.Up()); + setupRepeatButton(downButton, new Input.Down()); + + setupDefaultButton(selectButton, new Input.Select(), null); + } + + // Other buttons + setupDefaultButton(backButton, new Input.Back(), null); + setupDefaultButton(osdButton, new Input.ExecuteAction(Input.ExecuteAction.OSD), null); + setupDefaultButton(contextButton, new Input.ExecuteAction(Input.ExecuteAction.CONTEXTMENU), null); + + // Info button, v17 uses a different window to display codec info so check version number HostInfo hostInfo = hostManager.getHostInfo(); + if (hostInfo.getKodiVersionMajor() < 17) { + setupDefaultButton(infoButton, + new Input.ExecuteAction(Input.ExecuteAction.INFO), + new Input.ExecuteAction(Input.ExecuteAction.CODECINFO)); + } else { + setupDefaultButton(infoButton, + new Input.ExecuteAction(Input.ExecuteAction.INFO), + new Input.ExecuteAction(Input.ExecuteAction.PLAYERPROCESSINFO)); + } + + adjustRemoteButtons(); TypedArray styledAttributes = getActivity().getTheme().obtainStyledAttributes(new int[] { R.attr.iconFastForward, @@ -201,9 +253,53 @@ public class RemoteFragment extends Fragment buttons[i].setVisibility(shownItems.contains(String.valueOf(i)) ? View.VISIBLE : View.GONE); } +// // Pad main content view to account for bottom system bar +// UIUtils.setPaddingForSystemBars(getActivity(), root, false, false, true); + + // No clipping +// root.setClipToPadding(false); + return root; } + @TargetApi(21) + private void adjustRemoteButtons() { + Resources.Theme theme = getActivity().getTheme(); + TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] { + R.attr.remoteButtonColorFilter, + R.attr.contentBackgroundColor}); +// R.attr.remoteBackgroundColorFilter}); + Resources resources = getResources(); + int remoteButtonsColor = styledAttributes.getColor(styledAttributes.getIndex(0), resources.getColor(R.color.white)), + remoteBackgroundColor = styledAttributes.getColor(styledAttributes.getIndex(1), resources.getColor(R.color.dark_content_background_dim_70pct)); + styledAttributes.recycle(); + + leftButton.setColorFilter(remoteButtonsColor); + rightButton.setColorFilter(remoteButtonsColor); + upButton.setColorFilter(remoteButtonsColor); + downButton.setColorFilter(remoteButtonsColor); + + selectButton.setColorFilter(remoteButtonsColor); + backButton.setColorFilter(remoteButtonsColor); + infoButton.setColorFilter(remoteButtonsColor); + osdButton.setColorFilter(remoteButtonsColor); + contextButton.setColorFilter(remoteButtonsColor); + + + // On ICS the remote background isn't shown as the tinting isn't supported + //int backgroundResourceId = R.drawable.remote_background_square_black_alpha; + int backgroundResourceId = R.drawable.remote_background_square_black; + if (Utils.isLollipopOrLater()) { + remotePanel.setBackgroundTintList(ColorStateList.valueOf(remoteBackgroundColor)); + remotePanel.setBackgroundResource(backgroundResourceId); + } else if (Utils.isJellybeanOrLater()) { + BitmapDrawable background = new BitmapDrawable(getResources(), + BitmapFactory.decodeResource(getResources(), backgroundResourceId)); + background.setColorFilter(new PorterDuffColorFilter(remoteBackgroundColor, PorterDuff.Mode.SRC_IN)); + remotePanel.setBackground(background); + } + } + @Override public void onActivityCreated (Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -242,6 +338,91 @@ public class RemoteFragment extends Fragment }); } + private void setupRepeatButton(View button, final ApiMethod action) { + button.setOnTouchListener(new RepeatListener(UIUtils.initialButtonRepeatInterval, UIUtils.buttonRepeatInterval, + new View.OnClickListener() { + @Override + public void onClick(View v) { + action.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); + } + }, buttonInAnim, buttonOutAnim, getActivity().getApplicationContext())); + } + + private void setupDefaultButton(View button, + final ApiMethod clickAction, + final ApiMethod longClickAction) { + // Set animation + button.setOnTouchListener(feedbackTouchListener); + if (clickAction != null) { + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + UIUtils.handleVibration(getActivity()); + clickAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); + } + }); + } + if (longClickAction != null) { + button.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + UIUtils.handleVibration(getActivity()); + longClickAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); + return true; + } + }); + } + } + + private void setupEventServerButton(View button, final String action) { + final Packet packet = + new PacketBUTTON(ButtonCodes.MAP_REMOTE, action, false, true, true, (short)0, (byte)0); + button.setOnTouchListener(new RepeatListener(UIUtils.initialButtonRepeatInterval, UIUtils.buttonRepeatInterval, + new View.OnClickListener() { + @Override + public void onClick(View v) { + if (eventServerConnection != null) + eventServerConnection.sendPacket(packet); + } + }, buttonInAnim, buttonOutAnim, getActivity().getApplicationContext())); + } + + +// private void setupEventServerButton(View button, final String action) { +// short amount = 0; +// byte axis = 0; +// final Packet packetDown = +// new PacketBUTTON(ButtonCodes.MAP_REMOTE, action, true, true, false, amount, axis); +// final Packet packetUp = +// new PacketBUTTON(ButtonCodes.MAP_REMOTE, action, false, false, false, amount, axis); +// +// // Set animation and packet +// button.setOnTouchListener(new View.OnTouchListener() { +// @Override +// public boolean onTouch(View v, MotionEvent event) { +// switch (event.getAction()) { +// case MotionEvent.ACTION_DOWN: +// buttonInAnim.setFillAfter(true); +// v.startAnimation(buttonInAnim); +// eventServerConnection.sendPacket(packetDown); +// break; +// case MotionEvent.ACTION_UP: +// case MotionEvent.ACTION_CANCEL: +// v.startAnimation(buttonOutAnim); +// eventServerConnection.sendPacket(packetUp); +// break; +// } +// return false; +// } +// }); +// button.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// // Nothing to do +// } +// }); +// } + /** * Default callback for methods that don't return anything */ @@ -550,92 +731,11 @@ public class RemoteFragment extends Fragment } if (showRemote) { - controlPad.setVisibility(View.VISIBLE); + remotePanel.setVisibility(View.VISIBLE); buttonBarPanel.setVisibility(View.VISIBLE); } else { - controlPad.setVisibility(View.GONE); + remotePanel.setVisibility(View.GONE); buttonBarPanel.setVisibility(View.GONE); } } - - @Override - public void leftButtonClicked() { - if (eventServerConnection != null) { - eventServerConnection.sendPacket(leftButtonPacket); - } else { - leftButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - } - - @Override - public void rightButtonClicked() { - if (eventServerConnection != null) { - eventServerConnection.sendPacket(rightButtonPacket); - } else { - rightButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - } - - @Override - public void upButtonClicked() { - if (eventServerConnection != null) { - eventServerConnection.sendPacket(upButtonPacket); - } else { - upButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - } - - @Override - public void downButtonClicked() { - if (eventServerConnection != null) { - eventServerConnection.sendPacket(downButtonPacket); - } else { - downButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - } - - @Override - public void selectButtonClicked() { - if (eventServerConnection != null) { - eventServerConnection.sendPacket(selectButtonPack); - } else { - selectButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - } - - @Override - public void backButtonClicked() { - backButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - - @Override - public void infoButtonClicked() { - infoButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - - @Override - public boolean infoButtonLongClicked() { - ApiMethod action; - HostInfo hostInfo = hostManager.getHostInfo(); - - // Info button, v17 uses a different window to display codec info so check version number - if (hostInfo.getKodiVersionMajor() < 17) { - action = new Input.ExecuteAction(Input.ExecuteAction.CODECINFO); - } else { - action = new Input.ExecuteAction(Input.ExecuteAction.PLAYERPROCESSINFO); - } - action.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - - return true; - } - - @Override - public void contextButtonClicked() { - contextButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } - - @Override - public void osdButtonClicked() { - osdButtonAction.execute(hostManager.getConnection(), defaultActionCallback, callbackHandler); - } } diff --git a/app/src/main/java/org/xbmc/kore/ui/viewgroups/SquareGridLayout.java b/app/src/main/java/org/xbmc/kore/ui/viewgroups/SquareGridLayout.java deleted file mode 100644 index c2bab55..0000000 --- a/app/src/main/java/org/xbmc/kore/ui/viewgroups/SquareGridLayout.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017 Martijn Brekhof. All rights reserved. - * - * 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 org.xbmc.kore.ui.viewgroups; - - -import android.content.Context; -import android.support.v7.widget.GridLayout; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.ViewTreeObserver; -import android.widget.RelativeLayout; - -import org.xbmc.kore.utils.LogUtils; - -/** - * The square grid layout creates a square layout that will fit inside - * the boundaries provided by the parent layout. - */ -public class SquareGridLayout extends GridLayout { - - public SquareGridLayout(Context context) { - super(context); - fixForRelativeLayout(); - } - - public SquareGridLayout(Context context, AttributeSet attrs) { - super(context, attrs); - fixForRelativeLayout(); - } - - public SquareGridLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - fixForRelativeLayout(); - } - - @Override - protected void onMeasure(int widthSpec, int heightSpec) { - int width = MeasureSpec.getSize(widthSpec); - int height = MeasureSpec.getSize(heightSpec); - int size = Math.min(width, height); - - super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY)); - } - - /** - * When used in a relative layout we need to set the layout parameters to - * the correct size manually. Otherwise the grid layout will be stretched. - */ - private void fixForRelativeLayout() { - getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - ViewGroup.LayoutParams pParams = getLayoutParams(); - - if (pParams instanceof RelativeLayout.LayoutParams) { - int size = Math.min(getWidth(), getHeight()); - pParams.width = size; - pParams.height = size; - setLayoutParams(pParams); - } - - getViewTreeObserver().removeGlobalOnLayoutListener(this); - } - }); - } -} diff --git a/app/src/main/java/org/xbmc/kore/ui/widgets/ControlPad.java b/app/src/main/java/org/xbmc/kore/ui/widgets/ControlPad.java deleted file mode 100644 index 413dc7d..0000000 --- a/app/src/main/java/org/xbmc/kore/ui/widgets/ControlPad.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2017 Martijn Brekhof. All rights reserved. - * - * 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 org.xbmc.kore.ui.widgets; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.BitmapFactory; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.drawable.BitmapDrawable; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.ImageView; - -import org.xbmc.kore.R; -import org.xbmc.kore.ui.viewgroups.SquareGridLayout; -import org.xbmc.kore.utils.LogUtils; -import org.xbmc.kore.utils.RepeatListener; -import org.xbmc.kore.utils.Utils; - -import butterknife.ButterKnife; -import butterknife.InjectView; - -public class ControlPad extends SquareGridLayout - implements View.OnClickListener, View.OnLongClickListener { - private static final String TAG = LogUtils.makeLogTag(ControlPad.class); - - private static final int initialButtonRepeatInterval = 400; // ms - private static final int buttonRepeatInterval = 80; // ms - - public interface OnPadButtonsListener { - void leftButtonClicked(); - void rightButtonClicked(); - void upButtonClicked(); - void downButtonClicked(); - void selectButtonClicked(); - void backButtonClicked(); - void infoButtonClicked(); - boolean infoButtonLongClicked(); - void contextButtonClicked(); - void osdButtonClicked(); - } - - private OnPadButtonsListener onPadButtonsListener; - - @InjectView(R.id.select) ImageView selectButton; - @InjectView(R.id.left) ImageView leftButton; - @InjectView(R.id.right) ImageView rightButton; - @InjectView(R.id.up) ImageView upButton; - @InjectView(R.id.down) ImageView downButton; - @InjectView(R.id.back) ImageView backButton; - @InjectView(R.id.info) ImageView infoButton; - @InjectView(R.id.context) ImageView contextButton; - @InjectView(R.id.osd) ImageView osdButton; - - public ControlPad(Context context) { - super(context); - initializeView(context); - } - - public ControlPad(Context context, AttributeSet attrs) { - super(context, attrs); - initializeView(context); - } - - public ControlPad(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initializeView(context); - } - - @Override - public void setOnClickListener(@Nullable View.OnClickListener l) { - throw new Error("Use setOnPadButtonsListener(listener)"); - } - - @Override - public void setOnLongClickListener(@Nullable OnLongClickListener l) { - throw new Error("Use setOnPadButtonsListener(listener)"); - } - - public void setOnPadButtonsListener(OnPadButtonsListener onPadButtonsListener) { - this.onPadButtonsListener = onPadButtonsListener; - } - - private void initializeView(Context context) { - LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.remote_control_pad, this); - ButterKnife.inject(this, this); - - applyTheme(); - setupListeners(context); - } - - @Override - public void onClick(View v) { - if (onPadButtonsListener == null) - return; - - switch (v.getId()) { - case R.id.select: - onPadButtonsListener.selectButtonClicked(); - break; - case R.id.left: - onPadButtonsListener.leftButtonClicked(); - break; - case R.id.right: - onPadButtonsListener.rightButtonClicked(); - break; - case R.id.up: - onPadButtonsListener.upButtonClicked(); - break; - case R.id.down: - onPadButtonsListener.downButtonClicked(); - break; - case R.id.back: - onPadButtonsListener.backButtonClicked(); - break; - case R.id.info: - onPadButtonsListener.infoButtonClicked(); - break; - case R.id.context: - onPadButtonsListener.contextButtonClicked(); - break; - case R.id.osd: - onPadButtonsListener.osdButtonClicked(); - break; - default: - LogUtils.LOGD(TAG, "Unknown button "+v.getId()+" clicked"); - } - } - - @Override - public boolean onLongClick(View v) { - if ((onPadButtonsListener != null) && (v.getId() == R.id.info)) { - return onPadButtonsListener.infoButtonLongClicked(); - } - - return false; - } - - @TargetApi(21) - private void applyTheme() { - Resources.Theme theme = getContext().getTheme(); - TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] { - R.attr.remoteButtonColorFilter, - R.attr.contentBackgroundColor}); - Resources resources = getResources(); - int remoteButtonsColor = styledAttributes.getColor(styledAttributes.getIndex(0), resources.getColor(R.color.white)), - remoteBackgroundColor = styledAttributes.getColor(styledAttributes.getIndex(1), resources.getColor(R.color.dark_content_background_dim_70pct)); - styledAttributes.recycle(); - - leftButton.setColorFilter(remoteButtonsColor); - rightButton.setColorFilter(remoteButtonsColor); - upButton.setColorFilter(remoteButtonsColor); - downButton.setColorFilter(remoteButtonsColor); - - selectButton.setColorFilter(remoteButtonsColor); - backButton.setColorFilter(remoteButtonsColor); - infoButton.setColorFilter(remoteButtonsColor); - osdButton.setColorFilter(remoteButtonsColor); - contextButton.setColorFilter(remoteButtonsColor); - - - // On ICS the remote background isn't shown as the tinting isn't supported - //int backgroundResourceId = R.drawable.remote_background_square_black_alpha; - int backgroundResourceId = R.drawable.remote_background_square_black; - if (Utils.isLollipopOrLater()) { - setBackgroundTintList(ColorStateList.valueOf(remoteBackgroundColor)); - setBackgroundResource(backgroundResourceId); - } else if (Utils.isJellybeanOrLater()) { - BitmapDrawable background = new BitmapDrawable(getResources(), - BitmapFactory.decodeResource(getResources(), backgroundResourceId)); - background.setColorFilter(new PorterDuffColorFilter(remoteBackgroundColor, PorterDuff.Mode.SRC_IN)); - setBackground(background); - } - } - - private void setupListeners(Context context) { - final Animation buttonInAnim = AnimationUtils.loadAnimation(context, R.anim.button_in); - final Animation buttonOutAnim = AnimationUtils.loadAnimation(context, R.anim.button_out); - - RepeatListener repeatListener = new RepeatListener(initialButtonRepeatInterval, - buttonRepeatInterval, this, - buttonInAnim, buttonOutAnim, getContext()); - - OnTouchListener feedbackTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - buttonInAnim.setFillAfter(true); - v.startAnimation(buttonInAnim); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - v.startAnimation(buttonOutAnim); - break; - } - return false; - } - }; - - leftButton.setOnTouchListener(repeatListener); - rightButton.setOnTouchListener(repeatListener); - upButton.setOnTouchListener(repeatListener); - downButton.setOnTouchListener(repeatListener); - setupButton(selectButton, feedbackTouchListener); - setupButton(backButton, feedbackTouchListener); - setupButton(infoButton, feedbackTouchListener); - setupButton(contextButton, feedbackTouchListener); - setupButton(osdButton, feedbackTouchListener); - } - - private void setupButton(View button, OnTouchListener feedbackTouchListener) { - button.setOnTouchListener(feedbackTouchListener); - button.setOnClickListener(this); - button.setOnLongClickListener(this); - } -} diff --git a/app/src/main/java/org/xbmc/kore/utils/Utils.java b/app/src/main/java/org/xbmc/kore/utils/Utils.java index 8bdeb9c..c95f6fe 100644 --- a/app/src/main/java/org/xbmc/kore/utils/Utils.java +++ b/app/src/main/java/org/xbmc/kore/utils/Utils.java @@ -15,7 +15,6 @@ */ package org.xbmc.kore.utils; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -27,7 +26,6 @@ import android.os.Build; import android.os.Handler; import android.support.v4.app.Fragment; import android.text.TextUtils; -import android.util.DisplayMetrics; import android.widget.Toast; import org.xbmc.kore.R; @@ -243,18 +241,4 @@ public class Utils { } }, callbackHandler); } - - /** - * Returns the smallest width in density independent pixel size. - * Useful to determine in which swdp bucket the device is placed. - * @param activity - * @return the smallest width in density independent pixel size - */ - public static int getSmallestWidthDP(Activity activity) { - DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - float widthDp = metrics.widthPixels / metrics.density; - float heightDp = metrics.heightPixels / metrics.density; - return (int) Math.min(widthDp, heightDp); - } } diff --git a/app/src/main/res/layout-land/fragment_remote.xml b/app/src/main/res/layout-land/fragment_remote.xml index 3ff16f7..44a0e4e 100644 --- a/app/src/main/res/layout-land/fragment_remote.xml +++ b/app/src/main/res/layout-land/fragment_remote.xml @@ -15,19 +15,218 @@ limitations under the License. --> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout-sw360dp-land/fragment_remote.xml b/app/src/main/res/layout-sw360dp-land/fragment_remote.xml deleted file mode 100644 index 69e6d8e..0000000 --- a/app/src/main/res/layout-sw360dp-land/fragment_remote.xml +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw360dp/fragment_remote.xml b/app/src/main/res/layout-sw360dp/fragment_remote.xml deleted file mode 100644 index 7e61eb5..0000000 --- a/app/src/main/res/layout-sw360dp/fragment_remote.xml +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_remote.xml b/app/src/main/res/layout/fragment_remote.xml index d5e63b6..d54991e 100644 --- a/app/src/main/res/layout/fragment_remote.xml +++ b/app/src/main/res/layout/fragment_remote.xml @@ -18,105 +18,93 @@ + android:layout_height="match_parent"> - + + + android:layout_alignParentLeft="true" + android:layout_marginLeft="@dimen/remote_content_hmargin" + android:layout_marginRight="@dimen/remote_content_hmargin" + android:paddingTop="@dimen/remote_page_indicator_height"> - + - + android:layout_height="@dimen/default_icon_size" + android:layout_toRightOf="@id/art" + android:layout_toEndOf="@id/art" + android:layout_alignBottom="@id/art" + android:orientation="horizontal" + style="@style/ButtonBar" + android:background="?attr/contentBackgroundColor"> + + + + + - - - - - - - - - - - - - - - - - - + + + - + android:layout_marginBottom="@dimen/default_padding" + android:layout_centerHorizontal="true"> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/remote_control_pad.xml b/app/src/main/res/layout/remote_control_pad.xml deleted file mode 100644 index c250284..0000000 --- a/app/src/main/res/layout/remote_control_pad.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/remote_info_panel.xml b/app/src/main/res/layout/remote_info_panel.xml index c43ef76..fc0e867 100644 --- a/app/src/main/res/layout/remote_info_panel.xml +++ b/app/src/main/res/layout/remote_info_panel.xml @@ -20,7 +20,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/info_panel" android:layout_width="match_parent" - android:layout_height="@dimen/remote_poster_height" + android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentLeft="true" android:paddingTop="@dimen/remote_page_indicator_height" diff --git a/app/src/main/res/values-sw320dp/dimens.xml b/app/src/main/res/values-sw320dp/dimens.xml new file mode 100644 index 0000000..d9a03f4 --- /dev/null +++ b/app/src/main/res/values-sw320dp/dimens.xml @@ -0,0 +1,5 @@ + + + 58dp + 174dp + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index f5431bc..c89fe31 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -60,7 +60,6 @@ 98dp 140dp - 164dp 112dp 160dp