Implemented VolumeLevelIndicator widget (#406)

* Refactored NowPlayingFragment to use new widget
  * Refactored UIUtils.highlightImageView to reduce code duplication
This commit is contained in:
Martijn Brekhof 2017-06-22 19:37:00 +02:00 committed by Synced Synapse
parent 3be2d74f0a
commit 85bcd846f2
6 changed files with 151 additions and 104 deletions

View File

@ -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);
}

View File

@ -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);
}
};
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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"

View File

@ -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>