Skip to content

Commit e6876d5

Browse files
authored
fix: Add scrollable content to modern style settings dialogs (#5211)
1 parent f15003a commit e6876d5

File tree

8 files changed

+153
-139
lines changed

8 files changed

+153
-139
lines changed

extensions/shared/library/src/main/java/app/revanced/extension/shared/Utils.java

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import android.widget.FrameLayout;
4343
import android.widget.LinearLayout;
4444
import android.widget.RelativeLayout;
45+
import android.widget.ScrollView;
4546
import android.widget.TextView;
4647
import android.widget.Toast;
4748
import android.widget.Toolbar;
@@ -773,16 +774,15 @@ public static Pair<Dialog, LinearLayout> createCustomDialog(
773774
Dialog dialog = new Dialog(context);
774775
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // Remove default title bar.
775776

776-
// Create main layout.
777-
LinearLayout mainLayout = new LinearLayout(context);
778-
mainLayout.setOrientation(LinearLayout.VERTICAL);
779-
780777
// Preset size constants.
781778
final int dip4 = dipToPixels(4);
782779
final int dip8 = dipToPixels(8);
783780
final int dip16 = dipToPixels(16);
784781
final int dip24 = dipToPixels(24);
785782

783+
// Create main layout.
784+
LinearLayout mainLayout = new LinearLayout(context);
785+
mainLayout.setOrientation(LinearLayout.VERTICAL);
786786
mainLayout.setPadding(dip24, dip16, dip24, dip24);
787787
// Set rounded rectangle background.
788788
ShapeDrawable mainBackground = new ShapeDrawable(new RoundRectShape(
@@ -802,55 +802,71 @@ public static Pair<Dialog, LinearLayout> createCustomDialog(
802802
ViewGroup.LayoutParams.MATCH_PARENT,
803803
ViewGroup.LayoutParams.WRAP_CONTENT
804804
);
805-
layoutParams.setMargins(0, 0, 0, dip8);
805+
layoutParams.setMargins(0, 0, 0, dip16);
806806
titleView.setLayoutParams(layoutParams);
807807
mainLayout.addView(titleView);
808808
}
809809

810-
// Message (if not replaced by EditText).
811-
if (editText == null && message != null) {
812-
TextView messageView = new TextView(context);
813-
messageView.setText(message); // Supports Spanned (HTML).
814-
messageView.setTextSize(16);
815-
messageView.setTextColor(getAppForegroundColor());
816-
// Enable HTML link clicking if the message contains links.
817-
if (message instanceof Spanned) {
818-
messageView.setMovementMethod(LinkMovementMethod.getInstance());
810+
// Create content container (message/EditText) inside a ScrollView only if message or editText is provided.
811+
ScrollView contentScrollView = null;
812+
LinearLayout contentContainer = null;
813+
if (message != null || editText != null) {
814+
contentScrollView = new ScrollView(context);
815+
contentScrollView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
816+
contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
817+
if (editText != null) {
818+
ShapeDrawable scrollViewBackground = new ShapeDrawable(new RoundRectShape(
819+
createCornerRadii(10), null, null));
820+
scrollViewBackground.getPaint().setColor(getEditTextBackground());
821+
contentScrollView.setPadding(dip8, dip8, dip8, dip8);
822+
contentScrollView.setBackground(scrollViewBackground);
823+
contentScrollView.setClipToOutline(true);
819824
}
820-
LinearLayout.LayoutParams messageParams = new LinearLayout.LayoutParams(
825+
LinearLayout.LayoutParams contentParams = new LinearLayout.LayoutParams(
821826
ViewGroup.LayoutParams.MATCH_PARENT,
822-
ViewGroup.LayoutParams.WRAP_CONTENT
827+
0,
828+
1.0f // Weight to take available space.
823829
);
824-
messageParams.setMargins(0, dip8, 0, dip16);
825-
messageView.setLayoutParams(messageParams);
826-
mainLayout.addView(messageView);
827-
}
830+
contentScrollView.setLayoutParams(contentParams);
831+
contentContainer = new LinearLayout(context);
832+
contentContainer.setOrientation(LinearLayout.VERTICAL);
833+
contentScrollView.addView(contentContainer);
834+
835+
// Message (if not replaced by EditText).
836+
if (editText == null && message != null) {
837+
TextView messageView = new TextView(context);
838+
messageView.setText(message); // Supports Spanned (HTML).
839+
messageView.setTextSize(16);
840+
messageView.setTextColor(getAppForegroundColor());
841+
// Enable HTML link clicking if the message contains links.
842+
if (message instanceof Spanned) {
843+
messageView.setMovementMethod(LinkMovementMethod.getInstance());
844+
}
845+
LinearLayout.LayoutParams messageParams = new LinearLayout.LayoutParams(
846+
ViewGroup.LayoutParams.MATCH_PARENT,
847+
ViewGroup.LayoutParams.WRAP_CONTENT
848+
);
849+
messageView.setLayoutParams(messageParams);
850+
contentContainer.addView(messageView);
851+
}
828852

829-
// EditText (if provided).
830-
if (editText != null) {
831-
// Remove EditText from its current parent, if any.
832-
ViewGroup parent = (ViewGroup) editText.getParent();
833-
if (parent != null) {
834-
parent.removeView(editText);
853+
// EditText (if provided).
854+
if (editText != null) {
855+
// Remove EditText from its current parent, if any.
856+
ViewGroup parent = (ViewGroup) editText.getParent();
857+
if (parent != null) {
858+
parent.removeView(editText);
859+
}
860+
// Style the EditText to match the dialog theme.
861+
editText.setTextColor(getAppForegroundColor());
862+
editText.setBackgroundColor(Color.TRANSPARENT);
863+
editText.setPadding(0, 0, 0, 0);
864+
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(
865+
LinearLayout.LayoutParams.MATCH_PARENT,
866+
LinearLayout.LayoutParams.WRAP_CONTENT
867+
);
868+
contentContainer.addView(editText, editTextParams);
835869
}
836-
// Style the EditText to match the dialog theme.
837-
editText.setTextColor(getAppForegroundColor());
838-
editText.setBackgroundColor(isDarkModeEnabled() ? Color.BLACK : Color.WHITE);
839-
editText.setPadding(dip8, dip8, dip8, dip8);
840-
ShapeDrawable editTextBackground = new ShapeDrawable(new RoundRectShape(
841-
createCornerRadii(10), null, null));
842-
editTextBackground.getPaint().setColor(getEditTextBackground()); // Background color for EditText.
843-
editText.setBackground(editTextBackground);
844-
845-
LinearLayout.LayoutParams editTextParams = new LinearLayout.LayoutParams(
846-
LinearLayout.LayoutParams.MATCH_PARENT,
847-
LinearLayout.LayoutParams.WRAP_CONTENT
848-
);
849-
editTextParams.setMargins(0, dip8, 0, dip16);
850-
// Prevent buttons from moving off the screen by fixing the height of the EditText.
851-
final int maxHeight = (int) (context.getResources().getDisplayMetrics().heightPixels * 0.6);
852-
editText.setMaxHeight(maxHeight);
853-
mainLayout.addView(editText, 1, editTextParams);
854870
}
855871

856872
// Button container.
@@ -861,7 +877,7 @@ public static Pair<Dialog, LinearLayout> createCustomDialog(
861877
LinearLayout.LayoutParams.MATCH_PARENT,
862878
LinearLayout.LayoutParams.WRAP_CONTENT
863879
);
864-
buttonContainerParams.setMargins(0, dip8, 0, 0);
880+
buttonContainerParams.setMargins(0, dip16, 0, 0);
865881
buttonContainer.setLayoutParams(buttonContainerParams);
866882

867883
// Lists to track buttons.
@@ -1036,25 +1052,29 @@ public static Pair<Dialog, LinearLayout> createCustomDialog(
10361052
}
10371053
}
10381054

1055+
// Add ScrollView to main layout only if content exist.
1056+
if (contentScrollView != null) {
1057+
mainLayout.addView(contentScrollView);
1058+
}
10391059
mainLayout.addView(buttonContainer);
10401060
dialog.setContentView(mainLayout);
10411061

10421062
// Set dialog window attributes.
10431063
Window window = dialog.getWindow();
10441064
if (window != null) {
1045-
setDialogWindowParameters(context, window);
1065+
setDialogWindowParameters(window);
10461066
}
10471067

10481068
return new Pair<>(dialog, mainLayout);
10491069
}
10501070

1051-
public static void setDialogWindowParameters(Context context, Window window) {
1071+
public static void setDialogWindowParameters(Window window) {
10521072
WindowManager.LayoutParams params = window.getAttributes();
10531073

1054-
Resources resources = context.getResources();
1055-
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
1074+
DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
10561075
int portraitWidth = (int) (displayMetrics.widthPixels * 0.9);
1057-
if (resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
1076+
1077+
if (Resources.getSystem().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
10581078
portraitWidth = (int) Math.min(portraitWidth, displayMetrics.heightPixels * 0.9);
10591079
}
10601080
params.width = portraitWidth;
@@ -1199,7 +1219,7 @@ public static int getDialogBackgroundColor() {
11991219
return darkColor == Color.BLACK
12001220
// Lighten the background a little if using AMOLED dark theme
12011221
// as the dialogs are almost invisible.
1202-
? 0xFF0D0D0D
1222+
? 0xFF080808 // 3%
12031223
: darkColor;
12041224
}
12051225
return getThemeLightColor();

extensions/shared/library/src/main/java/app/revanced/extension/shared/checks/Check.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ static void issueWarning(Activity activity, Collection<Check> failedChecks) {
129129
ImageView iconView = new ImageView(activity);
130130
iconView.setImageResource(Utils.getResourceIdentifier("revanced_ic_dialog_alert", "drawable"));
131131
iconView.setColorFilter(Utils.getAppForegroundColor(), PorterDuff.Mode.SRC_IN);
132-
final int dip8 = dipToPixels(8);
133-
iconView.setPadding(0, dip8, 0, dip8);
132+
iconView.setPadding(0, 0, 0, 0);
134133
LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(
135134
LinearLayout.LayoutParams.WRAP_CONTENT,
136135
LinearLayout.LayoutParams.WRAP_CONTENT

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ColorPickerPreference.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
import android.view.View;
2525
import android.view.ViewGroup;
2626
import android.view.ViewParent;
27-
import android.widget.Button;
28-
import android.widget.EditText;
29-
import android.widget.LinearLayout;
30-
import android.widget.TextView;
27+
import android.widget.*;
3128

3229
import androidx.annotation.ColorInt;
3330

@@ -298,7 +295,6 @@ protected void showDialog(Bundle state) {
298295
// Horizontal layout for preview and EditText.
299296
LinearLayout inputLayout = new LinearLayout(context);
300297
inputLayout.setOrientation(LinearLayout.HORIZONTAL);
301-
inputLayout.setPadding(0, 0, 0, dipToPixels(10));
302298

303299
dialogColorPreview = new TextView(context);
304300
LinearLayout.LayoutParams previewParams = new LinearLayout.LayoutParams(
@@ -338,11 +334,23 @@ protected void showDialog(Bundle state) {
338334
paddingView.setLayoutParams(params);
339335
inputLayout.addView(paddingView);
340336

341-
// Create main container for color picker and input layout.
342-
LinearLayout container = new LinearLayout(context);
343-
container.setOrientation(LinearLayout.VERTICAL);
344-
container.addView(colorPicker);
345-
container.addView(inputLayout);
337+
// Create content container for color picker and input layout.
338+
LinearLayout contentContainer = new LinearLayout(context);
339+
contentContainer.setOrientation(LinearLayout.VERTICAL);
340+
contentContainer.addView(colorPicker);
341+
contentContainer.addView(inputLayout);
342+
343+
// Create ScrollView to wrap the content container.
344+
ScrollView contentScrollView = new ScrollView(context);
345+
contentScrollView.setVerticalScrollBarEnabled(false); // Disable vertical scrollbar.
346+
contentScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER); // Disable overscroll effect.
347+
LinearLayout.LayoutParams scrollViewParams = new LinearLayout.LayoutParams(
348+
LinearLayout.LayoutParams.MATCH_PARENT,
349+
0,
350+
1.0f
351+
);
352+
contentScrollView.setLayoutParams(scrollViewParams);
353+
contentScrollView.addView(contentContainer);
346354

347355
// Create custom dialog.
348356
final int originalColor = currentColor & 0x00FFFFFF;
@@ -391,9 +399,9 @@ protected void showDialog(Bundle state) {
391399
false // Do not dismiss dialog when onNeutralClick.
392400
);
393401

394-
// Add the custom container to the dialog's main layout.
402+
// Add the ScrollView to the dialog's main layout.
395403
LinearLayout dialogMainLayout = dialogPair.second;
396-
dialogMainLayout.addView(container, 1);
404+
dialogMainLayout.addView(contentScrollView, dialogMainLayout.getChildCount() - 1);
397405

398406
// Set up color picker listener with debouncing.
399407
// Add listener last to prevent callbacks from set calls above.

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/CustomDialogListPreference.java

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111
import android.view.LayoutInflater;
1212
import android.view.View;
1313
import android.view.ViewGroup;
14-
import android.widget.ArrayAdapter;
15-
import android.widget.ImageView;
16-
import android.widget.LinearLayout;
17-
import android.widget.ListView;
18-
import android.widget.TextView;
14+
import android.widget.*;
1915

2016
import androidx.annotation.NonNull;
2117

@@ -107,14 +103,16 @@ public CustomDialogListPreference(Context context) {
107103

108104
@Override
109105
protected void showDialog(Bundle state) {
106+
Context context = getContext();
107+
110108
// Create ListView.
111-
ListView listView = new ListView(getContext());
109+
ListView listView = new ListView(context);
112110
listView.setId(android.R.id.list);
113111
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
114112

115113
// Create custom adapter for the ListView.
116114
ListPreferenceArrayAdapter adapter = new ListPreferenceArrayAdapter(
117-
getContext(),
115+
context,
118116
Utils.getResourceIdentifier("revanced_custom_list_item_checked", "layout"),
119117
getEntries(),
120118
getEntryValues(),
@@ -137,7 +135,7 @@ protected void showDialog(Bundle state) {
137135

138136
// Create the custom dialog without OK button.
139137
Pair<Dialog, LinearLayout> dialogPair = Utils.createCustomDialog(
140-
getContext(),
138+
context,
141139
getTitle() != null ? getTitle().toString() : "",
142140
null,
143141
null,
@@ -149,35 +147,13 @@ protected void showDialog(Bundle state) {
149147
true
150148
);
151149

152-
Dialog dialog = dialogPair.first;
150+
// Add the ListView to the main layout.
153151
LinearLayout mainLayout = dialogPair.second;
154-
155-
// Measure content height before adding ListView to layout.
156-
// Otherwise, the ListView will push the buttons off the screen.
157-
int totalHeight = 0;
158-
int widthSpec = View.MeasureSpec.makeMeasureSpec(
159-
getContext().getResources().getDisplayMetrics().widthPixels,
160-
View.MeasureSpec.AT_MOST
161-
);
162-
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
163-
164-
for (int i = 0; i < adapter.getCount(); i++) {
165-
View listItem = adapter.getView(i, null, listView);
166-
listItem.measure(widthSpec, heightSpec);
167-
totalHeight += listItem.getMeasuredHeight();
168-
}
169-
170-
// Cap the height at maxHeight.
171-
int maxHeight = (int) (getContext().getResources().getDisplayMetrics().heightPixels * 0.6);
172-
int finalHeight = Math.min(totalHeight, maxHeight);
173-
174-
// Add ListView to the main layout with calculated height.
175152
LinearLayout.LayoutParams listViewParams = new LinearLayout.LayoutParams(
176153
LinearLayout.LayoutParams.MATCH_PARENT,
177-
finalHeight // Use calculated height directly.
154+
0,
155+
1.0f
178156
);
179-
final int marginHorizontal = dipToPixels(8);
180-
listViewParams.setMargins(0, marginHorizontal, 0, marginHorizontal);
181157
mainLayout.addView(listView, mainLayout.getChildCount() - 1, listViewParams);
182158

183159
// Handle item click to select value and dismiss dialog.
@@ -188,10 +164,10 @@ protected void showDialog(Bundle state) {
188164
adapter.setSelectedValue(selectedValue);
189165
adapter.notifyDataSetChanged();
190166
}
191-
dialog.dismiss();
167+
dialogPair.first.dismiss();
192168
});
193169

194170
// Show the dialog.
195-
dialog.show();
171+
dialogPair.first.show();
196172
}
197173
}

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/preference/ReVancedAboutPreference.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import android.os.Looper;
1818
import android.preference.Preference;
1919
import android.util.AttributeSet;
20+
import android.view.View;
2021
import android.view.Window;
2122
import android.webkit.WebView;
2223
import android.webkit.WebViewClient;
@@ -216,6 +217,8 @@ protected void onCreate(Bundle savedInstanceState) {
216217

217218
// Create WebView.
218219
WebView webView = new WebView(getContext());
220+
webView.setVerticalScrollBarEnabled(false); // Disable the vertical scrollbar.
221+
webView.setOverScrollMode(View.OVER_SCROLL_NEVER);
219222
webView.getSettings().setJavaScriptEnabled(true);
220223
webView.setWebViewClient(new OpenLinksExternallyWebClient());
221224
webView.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null);
@@ -228,7 +231,7 @@ protected void onCreate(Bundle savedInstanceState) {
228231
// Set dialog window attributes
229232
Window window = getWindow();
230233
if (window != null) {
231-
Utils.setDialogWindowParameters(getContext(), window);
234+
Utils.setDialogWindowParameters(window);
232235
}
233236
}
234237

0 commit comments

Comments
 (0)