mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
New menu system
This commit is contained in:
+153
-5
@@ -13,13 +13,18 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.Settings
|
||||
import com.futo.platformplayer.UIDialogs
|
||||
import com.futo.platformplayer.activities.MainActivity
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.dp
|
||||
import com.futo.platformplayer.fragment.mainactivity.MainActivityFragment
|
||||
import com.futo.platformplayer.fragment.mainactivity.main.*
|
||||
@@ -27,6 +32,10 @@ import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePayment
|
||||
import com.futo.platformplayer.states.StateSubscriptions
|
||||
import com.futo.platformplayer.views.AnyAdapterView
|
||||
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
|
||||
import com.futo.platformplayer.views.adapters.AnyAdapter
|
||||
import com.futo.platformplayer.views.pills.RoundButton
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.floor
|
||||
@@ -69,9 +78,15 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
private val _inflater: LayoutInflater;
|
||||
private val _subscribedActivity: MainActivity?;
|
||||
|
||||
private val _containerMoreHeader: ConstraintLayout;
|
||||
private val _toggleAirplaneMode: RoundButton;
|
||||
private val _togglePrivacy: RoundButton;
|
||||
|
||||
private var _overlayMore: FrameLayout;
|
||||
private var _overlayMoreBackground: FrameLayout;
|
||||
private var _layoutMoreButtons: LinearLayout;
|
||||
private var _layoutMoreButtons: RecyclerView;
|
||||
private val _layoutMoreButtonItems = arrayListOf<MenuButtonItem>();
|
||||
private var _layoutMoreButtonsAdapter: AnyAdapterView<MenuButtonItem, MenuButtonItemViewHolder>;
|
||||
private var _layoutBottomBarButtons: LinearLayout;
|
||||
|
||||
private var _moreVisible = false;
|
||||
@@ -90,10 +105,55 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
_inflater = inflater;
|
||||
inflater.inflate(R.layout.fragment_overview_bottom_bar, this);
|
||||
|
||||
_containerMoreHeader = findViewById(R.id.container_more_options);
|
||||
_toggleAirplaneMode = findViewById(R.id.toggle_airplane);
|
||||
_togglePrivacy = findViewById(R.id.toggle_privacy);
|
||||
|
||||
_toggleAirplaneMode.visibility = GONE;
|
||||
_toggleAirplaneMode.icon.setImageResource(R.drawable.ic_library);
|
||||
_toggleAirplaneMode.onClick.subscribe {
|
||||
if(StateApp.instance.privateMode) {
|
||||
_togglePrivacy.icon.setImageResource(R.drawable.ic_disabled_visible);
|
||||
//StateApp.instance.setPrivacyMode(false);
|
||||
UIDialogs.appToast("Airplane mode disabled");
|
||||
}
|
||||
else {
|
||||
_togglePrivacy.icon.setImageResource(R.drawable.ic_disabled_visible_purple);
|
||||
//StateApp.instance.setPrivacyMode(true);
|
||||
UIDialogs.appToast("Airplane mode enabled");
|
||||
}
|
||||
}
|
||||
_togglePrivacy.icon.setImageResource(R.drawable.ic_disabled_visible)
|
||||
_togglePrivacy.onClick.subscribe {
|
||||
if(StateApp.instance.privateMode) {
|
||||
_togglePrivacy.icon.setImageResource(R.drawable.ic_disabled_visible);
|
||||
StateApp.instance.setPrivacyMode(false);
|
||||
UIDialogs.appToast("Privacy mode disabled");
|
||||
}
|
||||
else {
|
||||
_togglePrivacy.icon.setImageResource(R.drawable.ic_disabled_visible_purple);
|
||||
StateApp.instance.setPrivacyMode(true);
|
||||
UIDialogs.appToast("Privacy mode enabled");
|
||||
}
|
||||
}
|
||||
|
||||
_overlayMore = findViewById(R.id.more_overlay);
|
||||
_overlayMoreBackground = findViewById(R.id.more_overlay_background);
|
||||
_layoutMoreButtons = findViewById(R.id.more_menu_buttons);
|
||||
_layoutBottomBarButtons = findViewById(R.id.bottom_bar_buttons)
|
||||
_layoutBottomBarButtons = findViewById(R.id.bottom_bar_buttons);
|
||||
|
||||
val totalWidthDp = resources.displayMetrics.widthPixels / resources.displayMetrics.density;
|
||||
val columns = MenuButtonItemViewHolder.getAutoSizeColumns(totalWidthDp);
|
||||
_layoutMoreButtonsAdapter = _layoutMoreButtons.asAny<MenuButtonItem, MenuButtonItemViewHolder>(_layoutMoreButtonItems,
|
||||
RecyclerView.VERTICAL, false, { button ->
|
||||
button.setAutoSize(totalWidthDp);
|
||||
button.parentFragment = this@MenuBottomBarView._fragment;
|
||||
button.onClick.subscribe {
|
||||
setMoreVisible(false);
|
||||
}
|
||||
})
|
||||
val layoutManager = GridLayoutManager(context, columns);
|
||||
_layoutMoreButtons.layoutManager = layoutManager;
|
||||
|
||||
_overlayMoreBackground.setOnClickListener { setMoreVisible(false); };
|
||||
|
||||
@@ -120,6 +180,8 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
}
|
||||
|
||||
private fun setMoreVisible(visible: Boolean) {
|
||||
|
||||
//TODO: issues with these bools
|
||||
if (_moreVisibleAnimating) {
|
||||
return
|
||||
}
|
||||
@@ -128,9 +190,12 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
val height = _moreButtons.firstOrNull()?.let {
|
||||
it.height.toFloat() + (it.layoutParams as MarginLayoutParams).bottomMargin
|
||||
} ?: return
|
||||
*/
|
||||
|
||||
_moreVisibleAnimating = true
|
||||
val moreOverlayBackground = _overlayMoreBackground
|
||||
@@ -142,14 +207,17 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
moreOverlay.visibility = VISIBLE
|
||||
val animations = arrayListOf<Animator>()
|
||||
animations.add(ObjectAnimator.ofFloat(moreOverlayBackground, "alpha", 0.0f, 1.0f).setDuration(duration))
|
||||
animations.add(ObjectAnimator.ofFloat(_layoutMoreButtons, "alpha", 0.0f, 1.0f).setDuration(duration))
|
||||
animations.add(ObjectAnimator.ofFloat(_containerMoreHeader, "alpha", 0.0f, 1.0f).setDuration(duration))
|
||||
_bottomButtons.find { it.definition.id == 99 }?.let {
|
||||
animations.add(ObjectAnimator.ofFloat(it, "alpha", 0.5f, 1.0f)
|
||||
.setDuration(duration));
|
||||
}
|
||||
|
||||
animations.add(ObjectAnimator.ofFloat(_layoutMoreButtons, "translationY", resources.displayMetrics.heightPixels.toFloat(), 0.0f).setDuration(duration))
|
||||
for ((index, button) in _moreButtons.withIndex()) {
|
||||
val i = _moreButtons.size - index
|
||||
animations.add(ObjectAnimator.ofFloat(button, "translationY", height * staggerFactor * (i + 1), 0.0f).setDuration(duration))
|
||||
//animations.add(ObjectAnimator.ofFloat(button, "translationY", height * staggerFactor * (i + 1), 0.0f).setDuration(duration))
|
||||
}
|
||||
|
||||
val animatorSet = AnimatorSet()
|
||||
@@ -164,14 +232,21 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
animations
|
||||
.add(ObjectAnimator.ofFloat(moreOverlayBackground, "alpha", 1.0f, 0.0f)
|
||||
.setDuration(duration))
|
||||
animations
|
||||
.add(ObjectAnimator.ofFloat(_layoutMoreButtons, "alpha", 1.0f, 0.0f)
|
||||
.setDuration(duration))
|
||||
animations
|
||||
.add(ObjectAnimator.ofFloat(_containerMoreHeader, "alpha", 1.0f, 0.0f)
|
||||
.setDuration(duration))
|
||||
_bottomButtons.find { it.definition.id == 99 }?.let {
|
||||
animations.add(ObjectAnimator.ofFloat(it, "alpha", 1.0f, 0.5f)
|
||||
.setDuration(duration));
|
||||
}
|
||||
|
||||
animations.add(ObjectAnimator.ofFloat(_layoutMoreButtons, "translationY", 0.0f, resources.displayMetrics.heightPixels.toFloat()).setDuration(duration))
|
||||
for ((index, button) in _moreButtons.withIndex()) {
|
||||
val i = _moreButtons.size - index
|
||||
animations.add(ObjectAnimator.ofFloat(button, "translationY", 0.0f, height * staggerFactor * (i + 1)).setDuration(duration))
|
||||
//animations.add(ObjectAnimator.ofFloat(button, "translationY", 0.0f, height * staggerFactor * (i + 1)).setDuration(duration))
|
||||
}
|
||||
|
||||
val animatorSet = AnimatorSet()
|
||||
@@ -183,11 +258,12 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
animatorSet.playTogether(animations)
|
||||
animatorSet.start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun updateBottomMenuButtons(buttons: MutableList<ButtonDefinition>, hasMore: Boolean) {
|
||||
if (hasMore) {
|
||||
buttons.add(ButtonDefinition(99, R.drawable.ic_more, R.drawable.ic_more, R.string.more, canToggle = false, { false }, { setMoreVisible(true) }))
|
||||
buttons.add(ButtonDefinition(99, R.drawable.ic_more, R.drawable.ic_more, R.string.more, canToggle = false, { false }, { setMoreVisible(!_moreVisible) }))
|
||||
}
|
||||
|
||||
_bottomButtons.clear();
|
||||
@@ -252,7 +328,9 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
insertedButtons++;
|
||||
}
|
||||
|
||||
val newButtons = mutableListOf<MenuButtonItem>();
|
||||
for (data in buttons) {
|
||||
/*
|
||||
val button = MenuButton(context, data, _fragment, true);
|
||||
button.setOnClickListener {
|
||||
updateMenuIcons()
|
||||
@@ -262,7 +340,12 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
|
||||
_moreButtons.add(button);
|
||||
_layoutMoreButtons.addView(button);
|
||||
*/
|
||||
val buttonItem = MenuButtonItem(data);
|
||||
newButtons.add(buttonItem);
|
||||
}
|
||||
_layoutMoreButtonsAdapter.setData(newButtons);
|
||||
_layoutMoreButtonsAdapter.notifyContentChanged();
|
||||
}
|
||||
|
||||
private fun updateMenuIcons() {
|
||||
@@ -350,6 +433,71 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
}
|
||||
|
||||
|
||||
class MenuButtonItem(val def: ButtonDefinition);
|
||||
class MenuButtonItemViewHolder(private val _viewGroup: ViewGroup): AnyAdapter.AnyViewHolder<MenuButtonItem>(
|
||||
LayoutInflater.from(_viewGroup.context).inflate(R.layout.list_menu_tile,
|
||||
_viewGroup, false)) {
|
||||
|
||||
val onClick = Event1<MenuButtonItem>();
|
||||
|
||||
val root: ConstraintLayout;
|
||||
val imageIcon: ImageView;
|
||||
val textName: TextView;
|
||||
|
||||
|
||||
var button: MenuButtonItem? = null;
|
||||
|
||||
var parentFragment: MenuBottomBarFragment? = null;
|
||||
|
||||
init {
|
||||
root = _view.findViewById(R.id.root);
|
||||
imageIcon = _view.findViewById(R.id.image_icon);
|
||||
textName = _view.findViewById(R.id.text_name);
|
||||
|
||||
root.setOnClickListener {
|
||||
button?.let {
|
||||
it.def.action(parentFragment ?: return@let);
|
||||
onClick.emit(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun bind(value: MenuButtonItem) {
|
||||
button = value;
|
||||
textName.text = _view.context.getString(value.def.string);
|
||||
imageIcon.setImageResource(value.def.iconActive);
|
||||
}
|
||||
|
||||
|
||||
fun setWidth(dp: Int) {
|
||||
root.updateLayoutParams {
|
||||
this.width = (dp - 12).dp(_viewGroup.context.resources);
|
||||
this.height = (dp - 12).dp(_viewGroup.context.resources);
|
||||
}
|
||||
imageIcon.updateLayoutParams {
|
||||
this.width = (dp - 46).dp(_viewGroup.context.resources);
|
||||
this.height = (dp - 46).dp(_viewGroup.context.resources);
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoSize(totalWidth: Float) {
|
||||
val dpWidth = totalWidth;
|
||||
val columns = Math.max(((dpWidth) / viewWidthDp).toInt(), 1);
|
||||
val remainder = dpWidth - columns * viewWidthDp;
|
||||
val targetSize = viewWidthDp + (remainder / columns).toInt();
|
||||
setWidth(targetSize);
|
||||
}
|
||||
|
||||
companion object {
|
||||
val viewWidthDp = 90;
|
||||
fun getAutoSizeColumns(totalWidth: Float): Int {
|
||||
val dpWidth = totalWidth;
|
||||
val columns = Math.max(((dpWidth) / viewWidthDp).toInt(), 1);
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
}
|
||||
class MenuButton: LinearLayout {
|
||||
val definition: ButtonDefinition;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#AA111111" />
|
||||
<stroke android:color="#111111" android:width="1dp" />
|
||||
<corners android:radius="4dp" />
|
||||
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
|
||||
</shape>
|
||||
@@ -25,14 +25,65 @@
|
||||
</FrameLayout>
|
||||
|
||||
<!--More Menu-->
|
||||
<LinearLayout
|
||||
android:id="@+id/more_menu_buttons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:gravity="end">
|
||||
</LinearLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container_more_options"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:gravity="right">
|
||||
|
||||
<com.futo.platformplayer.views.pills.RoundButton
|
||||
android:id="@+id/toggle_airplane"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp" />
|
||||
|
||||
<com.futo.platformplayer.views.pills.RoundButton
|
||||
android:id="@+id/toggle_privacy"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/button_close"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_close" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/more_menu_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/container_more_options"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
|
||||
android:gravity="end">
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="86dp"
|
||||
android:layout_height="146dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:background="@drawable/background_menu_round_4dp"
|
||||
android:id="@+id/root"
|
||||
android:clickable="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_icon"
|
||||
android:layout_height="54dp"
|
||||
android:layout_width="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintDimensionRatio="H,1,1"
|
||||
app:shapeAppearanceOverlay="@style/roundedCorners_4dp"
|
||||
app:srcCompat="@drawable/unknown_music"
|
||||
android:background="@drawable/video_thumbnail_outline"
|
||||
android:layout_marginLeft="18dp"
|
||||
android:layout_marginRight="18dp"
|
||||
android:layout_marginTop="12dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12dp"
|
||||
android:textColor="@color/white"
|
||||
android:fontFamily="@font/inter_medium"
|
||||
tools:text="The Beetles"
|
||||
android:maxLines="2"
|
||||
android:gravity="center"
|
||||
app:layout_constraintLeft_toRightOf="@id/image_icon"
|
||||
app:layout_constraintTop_toBottomOf="@id/image_icon"
|
||||
app:layout_constraintLeft_toLeftOf="@id/image_icon"
|
||||
app:layout_constraintRight_toRightOf="@id/image_icon"
|
||||
android:layout_marginTop="5dp"
|
||||
/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in New Issue
Block a user