mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-16 16:16:04 -04:00
Feat, wip[UI]: conditionnal visibility, reduced layout shifting, full screen scroll
This commit is contained in:
parent
17cce29c00
commit
04d6900bc4
@ -33,6 +33,7 @@ import android.view.View;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -1029,4 +1030,11 @@ public final class Tools {
|
|||||||
Intent sendIntent = Intent.createChooser(shareIntent, "latestlog.txt");
|
Intent sendIntent = Intent.createChooser(shareIntent, "latestlog.txt");
|
||||||
context.startActivity(sendIntent);
|
context.startActivity(sendIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int mesureTextviewHeight(TextView t) {
|
||||||
|
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(t.getWidth(), View.MeasureSpec.AT_MOST);
|
||||||
|
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||||
|
t.measure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
return t.getMeasuredHeight();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.fragments;
|
|||||||
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -12,6 +13,7 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.math.MathUtils;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
@ -35,6 +37,16 @@ import java.util.concurrent.Future;
|
|||||||
public class SearchModFragment extends Fragment {
|
public class SearchModFragment extends Fragment {
|
||||||
|
|
||||||
public static final String TAG = "SearchModFragment";
|
public static final String TAG = "SearchModFragment";
|
||||||
|
private View mOverlay;
|
||||||
|
private float mOverlayTopCache; // Padding cache reduce resource lookup
|
||||||
|
|
||||||
|
private final RecyclerView.OnScrollListener mOverlayPositionListener = new RecyclerView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
mOverlay.setY(MathUtils.clamp(mOverlay.getY() - dy, -mOverlay.getHeight(), mOverlayTopCache));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private TextView mSelectedVersion;
|
private TextView mSelectedVersion;
|
||||||
private Button mSelectVersionButton;
|
private Button mSelectVersionButton;
|
||||||
private EditText mSearchEditText;
|
private EditText mSearchEditText;
|
||||||
@ -49,8 +61,6 @@ public class SearchModFragment extends Fragment {
|
|||||||
|
|
||||||
private SearchFilters mSearchFilters;
|
private SearchFilters mSearchFilters;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SearchModFragment(){
|
public SearchModFragment(){
|
||||||
super(R.layout.fragment_mod_search);
|
super(R.layout.fragment_mod_search);
|
||||||
modpackApi = new CommonApi();
|
modpackApi = new CommonApi();
|
||||||
@ -62,7 +72,9 @@ public class SearchModFragment extends Fragment {
|
|||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
// You can only access resources after attaching to current context
|
// You can only access resources after attaching to current context
|
||||||
mModItemAdapter = new ModItemAdapter(getResources(), modpackApi);
|
mModItemAdapter = new ModItemAdapter(getResources(), modpackApi);
|
||||||
|
mOverlayTopCache = getResources().getDimension(R.dimen.fragment_padding_medium);
|
||||||
|
|
||||||
|
mOverlay = view.findViewById(R.id.search_mod_overlay);
|
||||||
mSearchEditText = view.findViewById(R.id.search_mod_edittext);
|
mSearchEditText = view.findViewById(R.id.search_mod_edittext);
|
||||||
mSearchProgressBar = view.findViewById(R.id.search_mod_progressbar);
|
mSearchProgressBar = view.findViewById(R.id.search_mod_progressbar);
|
||||||
mSelectedVersion = view.findViewById(R.id.search_mod_selected_mc_version_textview);
|
mSelectedVersion = view.findViewById(R.id.search_mod_selected_mc_version_textview);
|
||||||
@ -75,6 +87,8 @@ public class SearchModFragment extends Fragment {
|
|||||||
mRecyclerview.setLayoutManager(new LinearLayoutManager(getContext()));
|
mRecyclerview.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
mRecyclerview.setAdapter(mModItemAdapter);
|
mRecyclerview.setAdapter(mModItemAdapter);
|
||||||
|
|
||||||
|
mRecyclerview.addOnScrollListener(mOverlayPositionListener);
|
||||||
|
|
||||||
// Setup the expendable list behavior
|
// Setup the expendable list behavior
|
||||||
mSelectVersionButton.setOnClickListener(v -> VersionSelectorDialog.open(v.getContext(), true, (id, snapshot)->{
|
mSelectVersionButton.setOnClickListener(v -> VersionSelectorDialog.open(v.getContext(), true, (id, snapshot)->{
|
||||||
mSelectedVersion.setText(id);
|
mSelectedVersion.setText(id);
|
||||||
@ -93,6 +107,12 @@ public class SearchModFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
mRecyclerview.removeOnScrollListener(mOverlayPositionListener);
|
||||||
|
}
|
||||||
|
|
||||||
class SearchModTask implements SelfReferencingFuture.FutureInterface {
|
class SearchModTask implements SelfReferencingFuture.FutureInterface {
|
||||||
|
|
||||||
private final SearchFilters mTaskFilters;
|
private final SearchFilters mTaskFilters;
|
||||||
|
@ -31,10 +31,14 @@ import net.kdt.pojavlaunch.modloaders.modpacks.models.ModDetail;
|
|||||||
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
import net.kdt.pojavlaunch.modloaders.modpacks.models.ModItem;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHolder> {
|
public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHolder> {
|
||||||
private static final ModItem[] MOD_ITEMS_EMPTY = new ModItem[0];
|
private static final ModItem[] MOD_ITEMS_EMPTY = new ModItem[0];
|
||||||
|
|
||||||
|
/* Used when versions haven't loaded yet, default text to reduce layout shifting */
|
||||||
|
private final SimpleArrayAdapter<String> mLoadingAdapter = new SimpleArrayAdapter<>(Collections.singletonList("Loading"));
|
||||||
private final ModIconCache mIconCache = new ModIconCache();
|
private final ModIconCache mIconCache = new ModIconCache();
|
||||||
private ModItem[] mModItems;
|
private ModItem[] mModItems;
|
||||||
private final ModpackApi mModpackApi;
|
private final ModpackApi mModpackApi;
|
||||||
@ -60,7 +64,7 @@ public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHold
|
|||||||
private ImageReceiver mImageReceiver;
|
private ImageReceiver mImageReceiver;
|
||||||
|
|
||||||
/* Used to display available versions of the mod(pack) */
|
/* Used to display available versions of the mod(pack) */
|
||||||
private SimpleArrayAdapter<String> mVersionAdapter = new SimpleArrayAdapter<>(null);
|
private final SimpleArrayAdapter<String> mVersionAdapter = new SimpleArrayAdapter<>(null);
|
||||||
|
|
||||||
public ViewHolder(View view) {
|
public ViewHolder(View view) {
|
||||||
super(view);
|
super(view);
|
||||||
@ -77,7 +81,7 @@ public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHold
|
|||||||
mExtendedButton.getContext().getApplicationContext(),
|
mExtendedButton.getContext().getApplicationContext(),
|
||||||
mModDetail,
|
mModDetail,
|
||||||
mExtendedSpinner.getSelectedItemPosition()));
|
mExtendedSpinner.getSelectedItemPosition()));
|
||||||
mExtendedSpinner.setAdapter(mVersionAdapter);
|
mExtendedSpinner.setAdapter(mLoadingAdapter);
|
||||||
} else {
|
} else {
|
||||||
if(isExtended()) closeDetailedView();
|
if(isExtended()) closeDetailedView();
|
||||||
else openDetailedView();
|
else openDetailedView();
|
||||||
@ -184,12 +188,12 @@ public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHold
|
|||||||
private void openDetailedView(){
|
private void openDetailedView(){
|
||||||
mExtendedLayout.setVisibility(View.VISIBLE);
|
mExtendedLayout.setVisibility(View.VISIBLE);
|
||||||
mDescription.setMaxLines(99);
|
mDescription.setMaxLines(99);
|
||||||
mExtendedLayout.post(() -> {
|
|
||||||
// We need to align to the longer section
|
// We need to align to the longer section
|
||||||
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mExtendedLayout.getLayoutParams();
|
int futureBottom = mDescription.getBottom() + Tools.mesureTextviewHeight(mDescription) - mDescription.getHeight();
|
||||||
params.topToBottom = mDescription.getBottom() > mIconView.getBottom() ? R.id.mod_body_textview : R.id.mod_thumbnail_imageview;
|
ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) mExtendedLayout.getLayoutParams();
|
||||||
mExtendedLayout.setLayoutParams(params);
|
params.topToBottom = futureBottom > mIconView.getBottom() ? R.id.mod_body_textview : R.id.mod_thumbnail_imageview;
|
||||||
});
|
mExtendedLayout.setLayoutParams(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeDetailedView(){
|
private void closeDetailedView(){
|
||||||
@ -199,7 +203,7 @@ public class ModItemAdapter extends RecyclerView.Adapter<ModItemAdapter.ViewHold
|
|||||||
|
|
||||||
private void setDetailedStateDefault() {
|
private void setDetailedStateDefault() {
|
||||||
mExtendedButton.setEnabled(false);
|
mExtendedButton.setEnabled(false);
|
||||||
mExtendedSpinner.setAdapter(null);
|
mExtendedSpinner.setAdapter(mLoadingAdapter);
|
||||||
mExtendedErrorTextView.setVisibility(View.GONE);
|
mExtendedErrorTextView.setVisibility(View.GONE);
|
||||||
openDetailedView();
|
openDetailedView();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="@dimen/_2sdp" />
|
||||||
|
<padding
|
||||||
|
android:bottom="@dimen/padding_small"
|
||||||
|
android:left="@dimen/padding_small"
|
||||||
|
android:right="@dimen/padding_small"
|
||||||
|
android:top="@dimen/padding_small" />
|
||||||
|
<solid android:color="@color/background_overlay" />
|
||||||
|
</shape>
|
@ -6,75 +6,106 @@
|
|||||||
android:background="@color/background_app"
|
android:background="@color/background_app"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:paddingHorizontal="@dimen/fragment_padding_medium"
|
android:paddingHorizontal="@dimen/fragment_padding_medium"
|
||||||
android:paddingVertical="@dimen/fragment_padding_medium">
|
>
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/search_mod_edittext"
|
|
||||||
|
<!--
|
||||||
|
Cosmetic layout to have a better scrolling separation
|
||||||
|
-->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/search_mod_overlay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/background_line"
|
android:translationZ="10dp"
|
||||||
android:textSize="@dimen/_13ssp"
|
android:background="@drawable/background_overlay"
|
||||||
android:layout_marginBottom="@dimen/padding_large"
|
android:paddingHorizontal="@dimen/padding_medium"
|
||||||
|
android:paddingVertical="@dimen/padding_medium"
|
||||||
|
android:layout_marginTop="@dimen/fragment_padding_medium"
|
||||||
|
android:layout_marginHorizontal="@dimen/fragment_padding_medium"
|
||||||
|
|
||||||
android:ems="10"
|
|
||||||
android:hint="@string/hint_search_modpack"
|
|
||||||
android:inputType="textPersonName"
|
|
||||||
android:paddingHorizontal="@dimen/padding_heavy"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
/>
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/search_mod_progressbar"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/search_mod_edittext"
|
|
||||||
tools:layout_editor_absoluteX="13dp" />
|
|
||||||
|
|
||||||
<TextView
|
>
|
||||||
android:id="@+id/search_mod_mc_version_textview"
|
<!-- Search text -->
|
||||||
android:layout_width="wrap_content"
|
<EditText
|
||||||
android:layout_height="wrap_content"
|
android:id="@+id/search_mod_edittext"
|
||||||
android:text="@string/profiles_profile_version"
|
android:layout_width="match_parent"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/search_mod_selected_mc_version_textview"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintStart_toStartOf="@+id/search_mod_selected_mc_version_textview" />
|
android:background="@drawable/background_line"
|
||||||
|
android:textSize="@dimen/_13ssp"
|
||||||
|
android:translationZ="2dp"
|
||||||
|
|
||||||
<TextView
|
android:ems="10"
|
||||||
android:id="@+id/search_mod_selected_mc_version_textview"
|
android:hint="@string/hint_search_modpack"
|
||||||
android:layout_width="0dp"
|
android:inputType="textPersonName"
|
||||||
android:layout_height="wrap_content"
|
android:paddingHorizontal="@dimen/padding_heavy"
|
||||||
android:layout_marginVertical="32dp"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:layout_marginEnd="@dimen/padding_medium"
|
/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/search_mod_progressbar"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/search_mod_edittext"
|
||||||
|
tools:layout_editor_absoluteX="13dp" />
|
||||||
|
|
||||||
|
<!-- Version filter -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/search_mod_mc_version_textview"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/profiles_profile_version"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/search_mod_selected_mc_version_textview"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/search_mod_selected_mc_version_textview" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/search_mod_selected_mc_version_textview"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginVertical="32dp"
|
||||||
|
android:layout_marginEnd="@dimen/padding_medium"
|
||||||
|
|
||||||
|
android:background="@drawable/background_line"
|
||||||
|
android:hint="@string/version_select_hint"
|
||||||
|
android:paddingHorizontal="@dimen/padding_heavy"
|
||||||
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/search_mod_mc_version_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/search_mod_progressbar" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/search_mod_mc_version_button"
|
||||||
|
android:layout_width="@dimen/_72sdp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
|
||||||
|
android:text="@string/global_select"
|
||||||
|
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/search_mod_selected_mc_version_textview"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/search_mod_selected_mc_version_textview" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
android:background="@drawable/background_line"
|
|
||||||
android:hint="@string/version_select_hint"
|
|
||||||
android:paddingHorizontal="@dimen/padding_heavy"
|
|
||||||
android:textSize="@dimen/_13ssp"
|
|
||||||
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/search_mod_mc_version_button"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/search_mod_progressbar" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/search_mod_mc_version_button"
|
|
||||||
android:layout_width="@dimen/_72sdp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
|
|
||||||
android:text="@string/global_select"
|
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/search_mod_selected_mc_version_textview"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/search_mod_selected_mc_version_textview" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/search_mod_list"
|
android:id="@+id/search_mod_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="match_parent"
|
||||||
|
android:paddingTop="@dimen/_65sdp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/search_mod_selected_mc_version_textview"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout="@layout/view_mod_extended"
|
android:layout="@layout/view_mod_extended"
|
||||||
app:layout_constraintTop_toBottomOf="@id/mod_body_textview"/>
|
app:layout_constraintTop_toBottomOf="@id/mod_thumbnail_imageview"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
<color name="minebutton_color">#57CC33</color>
|
<color name="minebutton_color">#57CC33</color>
|
||||||
<color name="background_app">#181818</color>
|
<color name="background_app">#181818</color>
|
||||||
|
<color name="background_overlay">#464646</color>
|
||||||
<color name="background_status_bar">#242424</color>
|
<color name="background_status_bar">#242424</color>
|
||||||
<color name="background_bottom_bar">#232323</color>
|
<color name="background_bottom_bar">#232323</color>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user