That fuck shit the fascists are using
at master 430 lines 15 kB view raw
1/** 2 * Copyright (C) 2015 Open Whisper Systems 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17package org.tm.archive.util; 18 19import android.annotation.SuppressLint; 20import android.app.Activity; 21import android.content.Context; 22import android.content.res.Resources; 23import android.os.Build; 24import android.util.TypedValue; 25import android.view.Gravity; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.view.ViewGroup; 29import android.view.ViewStub; 30import android.view.ViewTreeObserver; 31import android.view.animation.AlphaAnimation; 32import android.view.animation.Animation; 33import android.view.inputmethod.InputMethodManager; 34import android.widget.EditText; 35import android.widget.TextView; 36 37import androidx.annotation.IdRes; 38import androidx.annotation.LayoutRes; 39import androidx.annotation.NonNull; 40import androidx.annotation.Nullable; 41import androidx.annotation.Px; 42import androidx.appcompat.app.AppCompatActivity; 43import androidx.appcompat.view.ContextThemeWrapper; 44import androidx.core.view.ViewCompat; 45import androidx.core.view.WindowInsetsCompat; 46import androidx.interpolator.view.animation.FastOutSlowInInterpolator; 47import androidx.lifecycle.Lifecycle; 48 49import org.signal.core.util.concurrent.ListenableFuture; 50import org.signal.core.util.concurrent.SettableFuture; 51import org.tm.archive.util.views.Stub; 52 53public final class ViewUtil { 54 55 private ViewUtil() { 56 } 57 58 public static void setMinimumHeight(@NonNull View view, @Px int minimumHeight) { 59 if (view.getMinimumHeight() != minimumHeight) { 60 view.setMinimumHeight(minimumHeight); 61 } 62 } 63 64 public static void focusAndMoveCursorToEndAndOpenKeyboard(@NonNull EditText input) { 65 int numberLength = input.getText().length(); 66 input.setSelection(numberLength, numberLength); 67 68 focusAndShowKeyboard(input); 69 } 70 71 public static void focusAndShowKeyboard(@NonNull View view) { 72 view.requestFocus(); 73 if (view.hasWindowFocus()) { 74 showTheKeyboardNow(view); 75 } else { 76 view.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() { 77 @Override 78 public void onWindowFocusChanged(boolean hasFocus) { 79 if (hasFocus) { 80 showTheKeyboardNow(view); 81 view.getViewTreeObserver().removeOnWindowFocusChangeListener(this); 82 } 83 } 84 }); 85 } 86 } 87 88 private static void showTheKeyboardNow(@NonNull View view) { 89 if (view.isFocused()) { 90 view.post(() -> { 91 InputMethodManager inputMethodManager = ServiceUtil.getInputMethodManager(view.getContext()); 92 inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); 93 }); 94 } 95 } 96 97 @SuppressWarnings("unchecked") 98 public static <T extends View> T inflateStub(@NonNull View parent, @IdRes int stubId) { 99 return (T)((ViewStub)parent.findViewById(stubId)).inflate(); 100 } 101 102 public static <T extends View> Stub<T> findStubById(@NonNull Activity parent, @IdRes int resId) { 103 return new Stub<>(parent.findViewById(resId)); 104 } 105 106 public static <T extends View> Stub<T> findStubById(@NonNull View parent, @IdRes int resId) { 107 return new Stub<>(parent.findViewById(resId)); 108 } 109 110 private static Animation getAlphaAnimation(float from, float to, int duration) { 111 final Animation anim = new AlphaAnimation(from, to); 112 anim.setInterpolator(new FastOutSlowInInterpolator()); 113 anim.setDuration(duration); 114 return anim; 115 } 116 117 public static void fadeIn(final @NonNull View view, final int duration) { 118 animateIn(view, getAlphaAnimation(0f, 1f, duration)); 119 } 120 121 public static ListenableFuture<Boolean> fadeOut(final @NonNull View view, final int duration) { 122 return fadeOut(view, duration, View.GONE); 123 } 124 125 public static ListenableFuture<Boolean> fadeOut(@NonNull View view, int duration, int visibility) { 126 return animateOut(view, getAlphaAnimation(1f, 0f, duration), visibility); 127 } 128 129 public static ListenableFuture<Boolean> animateOut(final @NonNull View view, final @NonNull Animation animation) { 130 return animateOut(view, animation, View.GONE); 131 } 132 133 public static ListenableFuture<Boolean> animateOut(final @NonNull View view, final @NonNull Animation animation, final int visibility) { 134 final SettableFuture future = new SettableFuture(); 135 if (view.getVisibility() == visibility) { 136 future.set(true); 137 } else { 138 view.clearAnimation(); 139 animation.reset(); 140 animation.setStartTime(0); 141 animation.setAnimationListener(new Animation.AnimationListener() { 142 @Override 143 public void onAnimationStart(Animation animation) {} 144 145 @Override 146 public void onAnimationRepeat(Animation animation) {} 147 148 @Override 149 public void onAnimationEnd(Animation animation) { 150 view.setVisibility(visibility); 151 future.set(true); 152 } 153 }); 154 view.startAnimation(animation); 155 } 156 return future; 157 } 158 159 public static void animateIn(final @NonNull View view, final @NonNull Animation animation) { 160 if (view.getVisibility() == View.VISIBLE) return; 161 162 view.clearAnimation(); 163 animation.reset(); 164 animation.setStartTime(0); 165 view.setVisibility(View.VISIBLE); 166 view.startAnimation(animation); 167 } 168 169 @SuppressWarnings("unchecked") 170 public static <T extends View> T inflate(@NonNull LayoutInflater inflater, 171 @NonNull ViewGroup parent, 172 @LayoutRes int layoutResId) 173 { 174 return (T)(inflater.inflate(layoutResId, parent, false)); 175 } 176 177 @SuppressLint("RtlHardcoded") 178 public static void setTextViewGravityStart(final @NonNull TextView textView, @NonNull Context context) { 179 if (isRtl(context)) { 180 textView.setGravity(Gravity.RIGHT); 181 } else { 182 textView.setGravity(Gravity.LEFT); 183 } 184 } 185 186 public static void mirrorIfRtl(View view, Context context) { 187 if (isRtl(context)) { 188 view.setScaleX(-1.0f); 189 } 190 } 191 192 public static boolean isLtr(@NonNull View view) { 193 return isLtr(view.getContext()); 194 } 195 196 public static boolean isLtr(@NonNull Context context) { 197 return context.getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; 198 } 199 200 public static boolean isRtl(@NonNull View view) { 201 return isRtl(view.getContext()); 202 } 203 204 public static boolean isRtl(@NonNull Context context) { 205 return context.getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; 206 } 207 208 public static float pxToDp(float px) { 209 return px / Resources.getSystem().getDisplayMetrics().density; 210 } 211 212 public static int dpToPx(Context context, int dp) { 213 return (int)((dp * context.getResources().getDisplayMetrics().density) + 0.5); 214 } 215 216 public static int dpToPx(int dp) { 217 return Math.round(dp * Resources.getSystem().getDisplayMetrics().density); 218 } 219 220 public static int dpToSp(int dp) { 221 return (int) (dpToPx(dp) / Resources.getSystem().getDisplayMetrics().scaledDensity); 222 } 223 224 public static int spToPx(float sp) { 225 return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, Resources.getSystem().getDisplayMetrics()); 226 } 227 228 public static void updateLayoutParams(@NonNull View view, int width, int height) { 229 view.getLayoutParams().width = width; 230 view.getLayoutParams().height = height; 231 view.requestLayout(); 232 } 233 234 public static void updateLayoutParamsIfNonNull(@Nullable View view, int width, int height) { 235 if (view != null) { 236 updateLayoutParams(view, width, height); 237 } 238 } 239 240 public static void setVisibilityIfNonNull(@Nullable View view, int visibility) { 241 if (view != null) { 242 view.setVisibility(visibility); 243 } 244 } 245 246 public static int getLeftMargin(@NonNull View view) { 247 if (isLtr(view)) { 248 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin; 249 } 250 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin; 251 } 252 253 public static int getRightMargin(@NonNull View view) { 254 if (isLtr(view)) { 255 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin; 256 } 257 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin; 258 } 259 260 public static int getTopMargin(@NonNull View view) { 261 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin; 262 } 263 264 public static int getBottomMargin(@NonNull View view) { 265 return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).bottomMargin; 266 } 267 268 public static void setLeftMargin(@NonNull View view, int margin) { 269 if (isLtr(view)) { 270 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin; 271 } else { 272 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin; 273 } 274 view.forceLayout(); 275 view.requestLayout(); 276 } 277 278 public static void setRightMargin(@NonNull View view, int margin) { 279 if (isLtr(view)) { 280 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin; 281 } else { 282 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin; 283 } 284 view.forceLayout(); 285 view.requestLayout(); 286 } 287 288 public static void setTopMargin(@NonNull View view, @Px int margin) { 289 setTopMargin(view, margin, true); 290 } 291 292 /** 293 * Sets the top margin of the view and optionally requests a new layout pass. 294 * 295 * @param view The view to set the margin on 296 * @param margin The margin to set 297 * @param requestLayout Whether requestLayout should be invoked on the view 298 */ 299 public static void setTopMargin(@NonNull View view, @Px int margin, boolean requestLayout) { 300 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = margin; 301 302 if (requestLayout) { 303 view.requestLayout(); 304 } 305 } 306 307 public static void setBottomMargin(@NonNull View view, @Px int margin) { 308 setBottomMargin(view, margin, true); 309 } 310 311 /** 312 * Sets the bottom margin of the view and optionally requests a new layout pass. 313 * 314 * @param view The view to set the margin on 315 * @param margin The margin to set 316 * @param requestLayout Whether requestLayout should be invoked on the view 317 */ 318 public static void setBottomMargin(@NonNull View view, @Px int margin, boolean requestLayout) { 319 ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).bottomMargin = margin; 320 if (requestLayout) { 321 view.requestLayout(); 322 } 323 } 324 325 public static int getWidth(@NonNull View view) { 326 return view.getLayoutParams().width; 327 } 328 329 public static void setPaddingTop(@NonNull View view, int padding) { 330 view.setPadding(view.getPaddingLeft(), padding, view.getPaddingRight(), view.getPaddingBottom()); 331 } 332 333 public static void setPaddingBottom(@NonNull View view, int padding) { 334 view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding); 335 } 336 337 public static void setPadding(@NonNull View view, int padding) { 338 view.setPadding(padding, padding, padding, padding); 339 } 340 341 public static void setPaddingStart(@NonNull View view, int padding) { 342 if (isLtr(view)) { 343 view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); 344 } else { 345 view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), padding, view.getPaddingBottom()); 346 } 347 } 348 349 public static void setPaddingEnd(@NonNull View view, int padding) { 350 if (isLtr(view)) { 351 view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), padding, view.getPaddingBottom()); 352 } else { 353 view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); 354 } 355 } 356 357 public static boolean isPointInsideView(@NonNull View view, float x, float y) { 358 int[] location = new int[2]; 359 360 view.getLocationOnScreen(location); 361 362 int viewX = location[0]; 363 int viewY = location[1]; 364 365 return x > viewX && x < viewX + view.getWidth() && 366 y > viewY && y < viewY + view.getHeight(); 367 } 368 369 public static int getStatusBarHeight(@NonNull View view) { 370 final WindowInsetsCompat rootWindowInsets = ViewCompat.getRootWindowInsets(view); 371 if (Build.VERSION.SDK_INT > 29 && rootWindowInsets != null) { 372 return rootWindowInsets.getInsets(WindowInsetsCompat.Type.statusBars()).top; 373 } else { 374 int result = 0; 375 int resourceId = view.getResources().getIdentifier("status_bar_height", "dimen", "android"); 376 if (resourceId > 0) { 377 result = view.getResources().getDimensionPixelSize(resourceId); 378 } 379 return result; 380 } 381 } 382 383 public static int getNavigationBarHeight(@NonNull View view) { 384 final WindowInsetsCompat rootWindowInsets = ViewCompat.getRootWindowInsets(view); 385 if (Build.VERSION.SDK_INT > 29 && rootWindowInsets != null) { 386 return rootWindowInsets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom; 387 } else { 388 int result = 0; 389 int resourceId = view.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); 390 if (resourceId > 0) { 391 result = view.getResources().getDimensionPixelSize(resourceId); 392 } 393 return result; 394 } 395 } 396 397 public static void hideKeyboard(@NonNull Context context, @NonNull View view) { 398 InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); 399 inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0); 400 } 401 402 /** 403 * Enables or disables a view and all child views recursively. 404 */ 405 public static void setEnabledRecursive(@NonNull View view, boolean enabled) { 406 view.setEnabled(enabled); 407 if (view instanceof ViewGroup) { 408 ViewGroup viewGroup = (ViewGroup) view; 409 for (int i = 0; i < viewGroup.getChildCount(); i++) { 410 setEnabledRecursive(viewGroup.getChildAt(i), enabled); 411 } 412 } 413 } 414 415 public static @Nullable Lifecycle getActivityLifecycle(@NonNull View view) { 416 return getActivityLifecycle(view.getContext()); 417 } 418 419 private static @Nullable Lifecycle getActivityLifecycle(@Nullable Context context) { 420 if (context instanceof ContextThemeWrapper) { 421 return getActivityLifecycle(((ContextThemeWrapper) context).getBaseContext()); 422 } 423 424 if (context instanceof AppCompatActivity) { 425 return ((AppCompatActivity) context).getLifecycle(); 426 } 427 428 return null; 429 } 430}