Implemented VolumeLevelIndicator widget (#406)
* Refactored NowPlayingFragment to use new widget * Refactored UIUtils.highlightImageView to reduce code duplication
This commit is contained in:
parent
3be2d74f0a
commit
85bcd846f2
|
@ -464,7 +464,7 @@ abstract public class AbstractInfoFragment extends AbstractFragment
|
|||
if (checkStoragePermission()) {
|
||||
if (Settings.allowedDownloadNetworkTypes(getActivity()) != 0) {
|
||||
listener.onClick(view);
|
||||
setButtonState(downloadButton, true);
|
||||
UIUtils.highlightImageView(getActivity(), downloadButton, true);
|
||||
} else {
|
||||
Toast.makeText(getActivity(), R.string.no_connection_type_selected, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ abstract public class AbstractInfoFragment extends AbstractFragment
|
|||
* @param state true if item has been watched/listened too, false otherwise
|
||||
*/
|
||||
protected void setDownloadButtonState(boolean state) {
|
||||
setButtonState(downloadButton, state);
|
||||
UIUtils.highlightImageView(getActivity(), downloadButton, state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -515,16 +515,8 @@ abstract public class AbstractInfoFragment extends AbstractFragment
|
|||
setToggleButtonState(pinUnpinButton, state);
|
||||
}
|
||||
|
||||
private void setButtonState(ImageButton button, boolean state) {
|
||||
if (state) {
|
||||
UIUtils.highlightImageView(getActivity(), button);
|
||||
} else {
|
||||
button.clearColorFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private void setToggleButtonState(ImageButton button, boolean state) {
|
||||
setButtonState(button, state);
|
||||
UIUtils.highlightImageView(getActivity(), button, state);
|
||||
button.setTag(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import android.widget.ImageView;
|
|||
import android.widget.PopupMenu;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -57,6 +56,7 @@ import org.xbmc.kore.jsonrpc.type.VideoType;
|
|||
import org.xbmc.kore.ui.generic.GenericSelectDialog;
|
||||
import org.xbmc.kore.ui.sections.video.AllCastActivity;
|
||||
import org.xbmc.kore.ui.widgets.MediaProgressIndicator;
|
||||
import org.xbmc.kore.ui.widgets.VolumeLevelIndicator;
|
||||
import org.xbmc.kore.utils.LogUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
@ -153,8 +153,7 @@ public class NowPlayingFragment extends Fragment
|
|||
@InjectView(R.id.media_undertitle) TextView mediaUndertitle;
|
||||
@InjectView(R.id.progress_info) MediaProgressIndicator mediaProgressIndicator;
|
||||
|
||||
@InjectView(R.id.volume_bar) SeekBar volumeSeekBar;
|
||||
@InjectView(R.id.volume_text) TextView volumeTextView;
|
||||
@InjectView(R.id.volume_level_indicator) VolumeLevelIndicator volumeLevelIndicator;
|
||||
|
||||
@InjectView(R.id.media_details) RelativeLayout mediaDetailsPanel;
|
||||
@InjectView(R.id.rating) TextView mediaRating;
|
||||
|
@ -202,6 +201,14 @@ public class NowPlayingFragment extends Fragment
|
|||
}
|
||||
});
|
||||
|
||||
volumeLevelIndicator.setOnVolumeChangeListener(new VolumeLevelIndicator.OnVolumeChangeListener() {
|
||||
@Override
|
||||
public void onVolumeChanged(int volume) {
|
||||
new Application.SetVolume(volume).execute(hostManager.getConnection(),
|
||||
defaultIntActionCallback, new Handler());
|
||||
}
|
||||
});
|
||||
|
||||
// // Pad main content view to overlap with bottom system bar
|
||||
// UIUtils.setPaddingForSystemBars(getActivity(), mediaPanel, false, false, true);
|
||||
// mediaPanel.setClipToPadding(false);
|
||||
|
@ -300,18 +307,10 @@ public class NowPlayingFragment extends Fragment
|
|||
// the mute state on the host. We do this to make it clear to the user that the button
|
||||
// was pressed.
|
||||
HostConnectionObserver.HostState hostState = hostConnectionObserver.getHostState();
|
||||
setVolumeState(!hostState.isVolumeMuted(), hostState.getVolumeLevel());
|
||||
UIUtils.highlightImageView(getActivity(), volumeMuteButton, !hostState.isVolumeMuted());
|
||||
|
||||
Application.SetMute action = new Application.SetMute();
|
||||
action.execute(hostManager.getConnection(), new ApiCallback<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
//We depend on the listener to correct the mute button state
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String description) { }
|
||||
}, callbackHandler);
|
||||
action.execute(hostManager.getConnection(), defaultBooleanActionCallback, new Handler());
|
||||
}
|
||||
|
||||
@OnClick(R.id.shuffle)
|
||||
|
@ -618,7 +617,8 @@ public class NowPlayingFragment extends Fragment
|
|||
|
||||
@Override
|
||||
public void applicationOnVolumeChanged(int volume, boolean muted) {
|
||||
setVolumeState(muted, volume);
|
||||
volumeLevelIndicator.setVolume(muted, volume);
|
||||
UIUtils.highlightImageView(getActivity(), volumeMuteButton, muted);
|
||||
}
|
||||
|
||||
// Ignore this
|
||||
|
@ -797,8 +797,6 @@ public class NowPlayingFragment extends Fragment
|
|||
}
|
||||
styledAttributes.recycle();
|
||||
|
||||
volumeSeekBar.setOnSeekBarChangeListener(volumeSeekbarChangeListener);
|
||||
|
||||
Resources resources = getActivity().getResources();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
@ -916,56 +914,4 @@ public class NowPlayingFragment extends Fragment
|
|||
if (plot == null) return null;
|
||||
return plot.replaceAll("\\[.*\\]", "");
|
||||
}
|
||||
|
||||
private int mediaTotalTime = 0,
|
||||
mediaCurrentTime = 0; // s
|
||||
private static final int SEEK_BAR_UPDATE_INTERVAL = 1000; // ms
|
||||
|
||||
/**
|
||||
* Sets UI volume state
|
||||
* @param muted whether volume is muted
|
||||
* @param volume
|
||||
*/
|
||||
private void setVolumeState(Boolean muted, int volume) {
|
||||
if (!isAdded()) return;
|
||||
|
||||
if (muted) {
|
||||
volumeSeekBar.setProgress(0);
|
||||
volumeTextView.setText(R.string.muted);
|
||||
|
||||
Resources.Theme theme = getActivity().getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[] {
|
||||
R.attr.colorAccent});
|
||||
volumeMuteButton.setColorFilter(
|
||||
styledAttributes.getColor(0,
|
||||
getActivity().getResources().getColor(R.color.accent_default)));
|
||||
styledAttributes.recycle();
|
||||
|
||||
} else {
|
||||
volumeSeekBar.setProgress(volume);
|
||||
volumeTextView.setText(String.valueOf(volume));
|
||||
volumeMuteButton.clearColorFilter();
|
||||
}
|
||||
}
|
||||
|
||||
private SeekBar.OnSeekBarChangeListener volumeSeekbarChangeListener = new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser) {
|
||||
volumeTextView.setText(String.valueOf(progress));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
new Application.SetVolume(seekBar.getProgress())
|
||||
.execute(hostManager.getConnection(), defaultIntActionCallback, callbackHandler);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.xbmc.kore.R;
|
||||
|
||||
public class VolumeLevelIndicator extends LinearLayout {
|
||||
private SeekBar volumeSeekBar;
|
||||
private TextView volumeTextView;
|
||||
|
||||
private OnVolumeChangeListener onVolumeChangeListener;
|
||||
|
||||
public interface OnVolumeChangeListener {
|
||||
void onVolumeChanged(int volume);
|
||||
}
|
||||
|
||||
public VolumeLevelIndicator(Context context) {
|
||||
super(context);
|
||||
initializeView(context);
|
||||
}
|
||||
|
||||
public VolumeLevelIndicator(Context context, AttributeSet attributeSet) {
|
||||
super(context, attributeSet);
|
||||
initializeView(context);
|
||||
}
|
||||
|
||||
private void initializeView(Context context) {
|
||||
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
inflater.inflate(R.layout.volume_level_indicator, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
volumeSeekBar = (SeekBar) findViewById(R.id.vli_seek_bar);
|
||||
volumeTextView = (TextView) findViewById(R.id.vli_volume_text);
|
||||
|
||||
volumeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser)
|
||||
volumeTextView.setText(String.valueOf(progress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
if (onVolumeChangeListener != null)
|
||||
onVolumeChangeListener.onVolumeChanged(seekBar.getProgress());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setOnVolumeChangeListener(OnVolumeChangeListener onVolumeChangeListener) {
|
||||
this.onVolumeChangeListener = onVolumeChangeListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets UI volume state
|
||||
* @param muted
|
||||
* @param volume
|
||||
*/
|
||||
public void setVolume(boolean muted, int volume) {
|
||||
if (muted) {
|
||||
volumeTextView.setText(R.string.muted);
|
||||
volumeSeekBar.setProgress(0);
|
||||
} else {
|
||||
volumeTextView.setText(String.valueOf(volume));
|
||||
volumeSeekBar.setProgress(volume);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -561,13 +561,23 @@ public class UIUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void highlightImageView(Context context, ImageView view) {
|
||||
Resources.Theme theme = context.getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[]{
|
||||
R.attr.colorAccent});
|
||||
view.setColorFilter(
|
||||
styledAttributes.getColor(0,
|
||||
context.getResources().getColor(R.color.accent_default)));
|
||||
styledAttributes.recycle();
|
||||
/**
|
||||
* Highlights an image view
|
||||
* @param context
|
||||
* @param view
|
||||
* @param highlight true if the image view should be highlighted, false otherwise
|
||||
*/
|
||||
public static void highlightImageView(Context context, ImageView view, boolean highlight) {
|
||||
if (highlight) {
|
||||
Resources.Theme theme = context.getTheme();
|
||||
TypedArray styledAttributes = theme.obtainStyledAttributes(new int[]{
|
||||
R.attr.colorAccent});
|
||||
view.setColorFilter(
|
||||
styledAttributes.getColor(styledAttributes.getIndex(0),
|
||||
context.getResources().getColor(R.color.accent_default)));
|
||||
styledAttributes.recycle();
|
||||
} else {
|
||||
view.clearColorFilter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,26 +169,12 @@
|
|||
style="@style/Widget.Button.Borderless"
|
||||
android:src="?attr/iconVolumeMute"
|
||||
android:contentDescription="@string/volume_mute"/>
|
||||
<LinearLayout
|
||||
<org.xbmc.kore.ui.widgets.VolumeLevelIndicator
|
||||
android:id="@+id/volume_level_indicator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="2"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/volume_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
style="@style/TextAppearance.Media.SmallDetails"
|
||||
android:textSize="10sp"/>
|
||||
<SeekBar
|
||||
android:id="@+id/volume_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:layout_gravity="bottom"/>
|
||||
</LinearLayout>
|
||||
|
||||
android:orientation="vertical"/>
|
||||
<ImageButton
|
||||
android:id="@+id/repeat"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<TextView
|
||||
android:id="@+id/vli_volume_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
style="@style/TextAppearance.Media.SmallDetails"
|
||||
android:textSize="10sp"/>
|
||||
<SeekBar
|
||||
android:id="@+id/vli_seek_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Button.Borderless"
|
||||
android:layout_gravity="bottom"/>
|
||||
</merge>
|
Loading…
Reference in New Issue