Java tutorial
/* * Copyright (C) 2014 Michell Bak * * 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 com.miz.utils; import android.animation.Animator; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.GradientDrawable; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; import android.support.v7.widget.Toolbar; import android.util.TypedValue; import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.miz.functions.Actor; import com.miz.functions.GridSeason; import com.miz.functions.MizLib; import com.miz.functions.WebMovie; import com.miz.mizuu.MizuuApplication; import com.miz.mizuu.R; import com.miz.views.ObservableScrollView; import com.squareup.picasso.Picasso; import java.util.List; import static com.miz.functions.PreferenceKeys.GRID_ITEM_SIZE; public class ViewUtils { private ViewUtils() { } // No instantiation /** * Returns a actor card with name, character, image and click listener. * @param context * @param picasso * @param actor * @return */ @SuppressLint("InflateParams") public static View setupActorCard(final Activity context, Picasso picasso, final Actor actor) { View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small, null); // Load image picasso.load(actor.getUrl()).placeholder(R.color.card_background_dark).error(R.drawable.noactor) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set title ((TextView) v.findViewById(R.id.text)).setText(actor.getName()); ((TextView) v.findViewById(R.id.text)).setTypeface(TypefaceUtils.getRobotoMedium(context)); // Set subtitle ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setText(actor.getCharacter()); ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setSingleLine(true); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { context.startActivity(IntentUtils.getActorIntent(context, actor)); } }); return v; } /** * Returns a movie card with title, release date, image and click listener. * @param context * @param picasso * @param movie * @return */ @SuppressLint("InflateParams") public static View setupMovieCard(final Activity context, Picasso picasso, final WebMovie movie) { final View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small, null); // Load image picasso.load(movie.getUrl()).placeholder(R.color.card_background_dark).error(R.drawable.loading_image) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set title ((TextView) v.findViewById(R.id.text)).setText(movie.getTitle()); ((TextView) v.findViewById(R.id.text)).setTypeface(TypefaceUtils.getRobotoMedium(context)); // Set subtitle ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setText(movie.getSubtitle()); ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setSingleLine(true); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(context, v.findViewById(R.id.cover), "cover"); ActivityCompat.startActivity(context, IntentUtils.getTmdbMovieDetails(context, movie), options.toBundle()); } }); return v; } /** * Returns a TV show card with title, release date, image and click listener. * @param context * @param picasso * @param show * @return */ @SuppressLint("InflateParams") public static View setupTvShowCard(final Context context, Picasso picasso, final WebMovie show) { View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small, null); // Load image picasso.load(show.getUrl()).placeholder(R.color.card_background_dark).error(R.drawable.loading_image) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set title ((TextView) v.findViewById(R.id.text)).setText(show.getTitle()); ((TextView) v.findViewById(R.id.text)).setTypeface(TypefaceUtils.getRobotoMedium(context)); // Set subtitle ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setText(show.getSubtitle()); ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setSingleLine(true); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { context.startActivity(IntentUtils.getTmdbTvShowLink(context, show)); } }); return v; } /** * Returns a TV show season card with title, release date, image and click listener. * @param context * @param picasso * @param season * @return */ @SuppressLint("InflateParams") public static View setupTvShowSeasonCard(final Activity context, Picasso picasso, final GridSeason season, final int toolbarColor) { final View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small, null); // Load image picasso.load(season.getCover()).placeholder(R.color.card_background_dark).error(R.drawable.loading_image) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set title ((TextView) v.findViewById(R.id.text)).setText(season.getHeaderText()); ((TextView) v.findViewById(R.id.text)).setTypeface(TypefaceUtils.getRobotoMedium(context)); // Set subtitle ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setText(season.getSimpleSubtitleText()); ((TextView) v.findViewById(R.id.gridCoverSubtitle)).setSingleLine(true); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { context.startActivityForResult(IntentUtils.getTvShowSeasonIntent(context, season.getShowId(), season.getSeason(), season.getEpisodeCount(), toolbarColor), 0); } }); return v; } /** * Returns a photo card with image and click listener. * @param context * @param picasso * @param url * @param items * @param index * @return */ @SuppressLint("InflateParams") public static View setupPhotoCard(final Context context, Picasso picasso, final String url, final List<String> items, final int index) { final View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small_no_text, null); // Load image picasso.load(url).placeholder(R.color.card_background_dark).error(R.drawable.noactor) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { context.startActivity(IntentUtils.getActorPhotoIntent(context, items, index)); } }); return v; } /** * Returns a photo card with image and click listener. * @param context * @param picasso * @param url * @param items * @param index * @return */ @SuppressLint("InflateParams") public static View setupTaggedPhotoCard(final Context context, Picasso picasso, final String url, final List<String> items, final int index) { View v = LayoutInflater.from(context).inflate(R.layout.horizontal_grid_item_small_landscape_no_text, null); // Load image picasso.load(url).placeholder(R.color.card_background_dark).error(R.drawable.noactor) .config(MizuuApplication.getBitmapConfig()).into(((ImageView) v.findViewById(R.id.cover))); // Set click listener v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { context.startActivity(IntentUtils.getActorTaggedPhotoIntent(context, items, index)); } }); return v; } /** * Animates the transition when changing the maxLines * attribute of a TextView. * @param text * @param maxLines */ public static void animateTextViewMaxLines(TextView text, int maxLines) { try { ObjectAnimator animation = ObjectAnimator.ofInt(text, "maxLines", maxLines); animation.setInterpolator(new AccelerateInterpolator()); animation.setDuration(200); animation.start(); } catch (Exception e) { // Some devices crash at runtime when using the ObjectAnimator text.setMaxLines(maxLines); } } public static void animateFabJump(View fab, Animator.AnimatorListener listener) { try { ObjectAnimator animation = ObjectAnimator.ofFloat(fab, "translationY", -10f, -5f, 0f, 5f, 10f, 5f, 0f, -5f, -10f, -5f, 0f); animation.setDuration(350); animation.addListener(listener); animation.start(); } catch (Exception e) { // Some devices crash at runtime when using the ObjectAnimator } } private static int defaultTitleTextColor = -1; /** * Update the Toolbar background color and title. * @param activity * @param toolbar * @param alpha * @param title * @param color */ public static void updateToolbarBackground(Activity activity, Toolbar toolbar, int alpha, String title, int color) { if (defaultTitleTextColor == -1) { int[] textColorAttr = new int[] { R.attr.actionMenuTextColor }; TypedValue typedValue = new TypedValue(); int indexOfAttrTextColor = 0; TypedArray a = activity.obtainStyledAttributes(typedValue.data, textColorAttr); defaultTitleTextColor = a.getColor(indexOfAttrTextColor, -1); a.recycle(); } toolbar.setTitle(title); toolbar.setTitleTextColor(adjustAlpha(defaultTitleTextColor, alpha)); int toolbarColor = adjustAlpha(color, alpha); if (MizLib.hasJellyBean()) { int topColor = darkenColor(color, alpha / 255f); topColor = adjustAlpha(topColor, Math.max(125, alpha)); int[] colors = { topColor, toolbarColor }; toolbar.setBackground(new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors)); } else { toolbar.setBackgroundColor(toolbarColor); } } public static int adjustAlpha(int color, int alpha) { int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); return Color.argb(alpha, red, green, blue); } public static int darkenColor(int color, float factor) { final float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= factor; return Color.HSVToColor(hsv); } public static boolean isTranslucentDecorAvailable(Context context) { int id = context.getResources().getIdentifier("config_enableTranslucentDecor", "bool", "android"); return (id == 0) && context.getResources().getBoolean(id); } public static int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } public static int getNavigationDrawerWidth(Context context) { int drawerWidth; // The navigation drawer should have a width equal to // the screen width minus the Toolbar height - at least // on mobile devices. Tablets are accounted for below. int toolbarHeight = MizLib.getActionBarHeight(context); // Get the display size Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); Point size = new Point(); display.getSize(size); // Get the smallest number int smallestDisplayWidth = Math.min(size.x, size.y); // Calculate the drawer width drawerWidth = smallestDisplayWidth - toolbarHeight; // Make sure that the calculated drawer width // isn't greater than the max width, i.e. // 5 times the standard increment (56dp for // mobile or 64dp for tablets). int maxWidth = MizLib.convertDpToPixels(context, 5 * (MizLib.isTablet(context) ? 64 : 56)); if (drawerWidth > maxWidth) drawerWidth = maxWidth; return drawerWidth; } /** * Since Toolbar needs to be bigger than the default height in some cases, * this method will change the height to include the status bar on Kitkat and newer. * @param context * @param toolbar */ public static void setProperToolbarSize(Context context, Toolbar toolbar) { toolbar.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, MizLib.hasKitKat() ? MizLib.getActionBarAndStatusBarHeight(context) : MizLib.getActionBarHeight(context))); } public static void setupWindowFlagsForStatusbarOverlay(Window window, boolean setBackgroundResource) { if (MizLib.isKitKat()) { // If we're running on KitKat, we want to enable // the translucent status bar window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } if (MizLib.hasKitKat()) { // If we're running on KitKat or above, we want to show // the background image beneath the status bar as well. window.getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); } // Make the status bar color transparent to begin with if (MizLib.hasLollipop()) window.setStatusBarColor(Color.TRANSPARENT); // If requested, set a background resource on the Window object if (setBackgroundResource) window.setBackgroundDrawableResource(R.drawable.bg); } public static void setLayoutParamsForDetailsEmptyView(Context context, View layout, ImageView background, ObservableScrollView scrollView, ViewTreeObserver.OnGlobalLayoutListener listener) { if (!MizLib.isPortrait(context)) { // Let's set the size of the empty view on the scroll container View empty = layout.findViewById(R.id.empty_view); if (empty == null) return; // First, we get the height of the background image, since that // fills the available screen estate in its entirety int fullHeight = background.getHeight(); // Then we get the content height - this is how much of the content // will be shown on the screen at a minimum int contentHeight = context.getResources().getDimensionPixelSize(R.dimen.content_details_main_height); // Finally we set the empty view to fill the width and have a height // that fills the gap between the full height and content height empty.setLayoutParams( new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, fullHeight - contentHeight)); } // Remove the ViewTreeObserver when we're done :-) MizLib.removeViewTreeObserver(scrollView.getViewTreeObserver(), listener); } public static void handleOnScrollChangedEvent(Activity activity, View layout, View background, String title, int height, int t, Toolbar toolbar, int toolbarColor) { final int headerHeight = (MizLib.isPortrait(activity) ? background.getHeight() : layout.findViewById(R.id.empty_view).getHeight()) - height; final float ratio = (float) Math.min(Math.max(t, 0), headerHeight) / headerHeight; final int newAlpha = (int) (ratio * 255); // Update the Toolbar ViewUtils.updateToolbarBackground(activity, toolbar, newAlpha, title, toolbarColor); if (MizLib.isPortrait(activity)) { // Such parallax, much wow background.setPadding(0, (int) (t / 1.5), 0, 0); } // Update scroll background in landscape mode if (!MizLib.isPortrait(activity)) { View v = layout.findViewById(R.id.background_view); View v2 = layout.findViewById(R.id.background_view_more); final int backgroundAlpha = (int) (ratio * 15) + 240; v.setBackgroundColor(ViewUtils.adjustAlpha(Color.parseColor("#303030"), backgroundAlpha)); v2.setBackgroundColor(ViewUtils.adjustAlpha(Color.parseColor("#303030"), backgroundAlpha)); } } public static void setToolbarAndStatusBarColor(android.support.v7.app.ActionBar actionBar, Window window, int color) { if (color != 0) { actionBar.setBackgroundDrawable(new ColorDrawable(color)); if (MizLib.hasLollipop()) window.setStatusBarColor(color); } } public static int getGridViewThumbSize(Context context) { int thumbSize = 0; String thumbnailSize = PreferenceManager.getDefaultSharedPreferences(context).getString(GRID_ITEM_SIZE, context.getString(R.string.normal)); if (thumbnailSize.equals(context.getString(R.string.large))) thumbSize = (int) (context.getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size) * 1.33); else if (thumbnailSize.equals(context.getString(R.string.normal))) thumbSize = (context.getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size) * 1); else thumbSize = (int) (context.getResources().getDimensionPixelSize(R.dimen.image_thumbnail_size) * 0.75); return thumbSize; } }