Java tutorial
/* * Copyright 2015 sourcestream GmbH * * 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 de.sourcestream.movieDB.controller; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.Intent; import android.content.pm.ActivityInfo; import android.net.ParseException; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v4.widget.DrawerLayout; import android.support.wearable.view.CircledImageView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.TranslateAnimation; import android.widget.AbsListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.Toast; import com.google.android.gms.analytics.HitBuilders; import com.google.android.gms.analytics.Tracker; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import de.sourcestream.movieDB.MainActivity; import de.sourcestream.movieDB.MovieDB; import de.sourcestream.movieDB.R; import de.sourcestream.movieDB.adapter.CastDetailsSlideAdapter; import de.sourcestream.movieDB.helper.ObservableScrollViewCallbacks; import de.sourcestream.movieDB.helper.ScrollState; import de.sourcestream.movieDB.helper.Scrollable; import de.sourcestream.movieDB.model.MovieModel; import de.sourcestream.movieDB.model.SimilarModel; import de.sourcestream.movieDB.view.MovieDetailsSlidingTabLayout; import de.sourcestream.movieDB.view.ObservableParallaxScrollView; /** * Cast details */ public class CastDetails extends Fragment implements ObservableScrollViewCallbacks { private MainActivity activity; private View rootView; private int currentId; private int timeOut; private HttpURLConnection conn; private String title; private Bundle save; private ArrayList<MovieModel> moviesList; private MovieModel movieModel; private ProgressBar spinner; private int moreIconCheck; private CircledImageView moreIcon; private CircledImageView homeIcon; private int homeIconCheck; private int galleryIconCheck; private CircledImageView galleryIcon; private ArrayList<String> galleryList; private onGalleryIconClick onGalleryIconClick; private onMoreIconClick onMoreIconClick; private onHomeIconClick onHomeIconClick; private MovieDetailsSlidingTabLayout mSlidingTabLayout; private ViewPager mViewPager; private CastDetailsSlideAdapter castDetailsSlideAdapter; private onPageChangeSelected onPageChangeSelected; private TranslateAnimation downAnimation; private DownAnimationListener downAnimationListener; private TranslateAnimation upAnimation; private UpAnimationListener upAnimationListener; private TranslateAnimation iconUpAnimation; private IconUpAnimationListener iconUpAnimationListener; private TranslateAnimation iconDownAnimation; private IconDownAnimationListener iconDownAnimationListener; private CastDetailsInfo castDetailsInfo; private CastDetailsCredits castDetailsCredits; private CastDetailsBiography castDetailsBiography; private int castDetailsInfoScrollY; private boolean addToBackStack; private String homeIconUrl; private float oldScrollY; private float dy; private float upDy; private float downDy; private float downDyTrans; private boolean upDyKey; private boolean downDyKey; private float scrollSpeed = 2.2F; private int currPos; private boolean infoTabScrollPosUpdated; private JSONAsyncTask request; private int iconMarginConstant; private int iconMarginLandscape; private int iconConstantSpecialCase; private int twoIcons; private int twoIconsToolbar; private int oneIcon; private int oneIconToolbar; private float scale; private boolean phone; private int hideThreshold; private int minThreshold; private int iconDirection; private boolean noCredits; /** * Called to do initial creation of a fragment. * This is called after onAttach(Activity) and before onCreateView(LayoutInflater, ViewGroup, Bundle). * * @param savedInstanceState If the fragment is being re-created from a previous saved state, this is the state. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) save = savedInstanceState.getBundle("save"); } /** * Called to have the fragment instantiate its user interface view. * * @param inflater sets the layout for the current view. * @param container the container which holds the current view. * @param savedInstanceState If non-null, this fragment is being re-constructed from a previous saved state as given here. * Return the View for the fragment's UI, or null. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); activity = ((MainActivity) getActivity()); movieModel = new MovieModel(); onGalleryIconClick = new onGalleryIconClick(); onMoreIconClick = new onMoreIconClick(); onHomeIconClick = new onHomeIconClick(); onPageChangeSelected = new onPageChangeSelected(); downAnimationListener = new DownAnimationListener(); upAnimationListener = new UpAnimationListener(); iconUpAnimationListener = new IconUpAnimationListener(); iconDownAnimationListener = new IconDownAnimationListener(); phone = getResources().getBoolean(R.bool.portrait_only); scale = getResources().getDisplayMetrics().density; if (phone) { hideThreshold = (int) (-105 * scale); minThreshold = (int) (-49 * scale); } else { hideThreshold = (int) (-100 * scale); minThreshold = (int) (-42 * scale); } if (currentId != this.getArguments().getInt("id") || this.timeOut == 1) { rootView = inflater.inflate(R.layout.castdetails, container, false); spinner = (ProgressBar) rootView.findViewById(R.id.progressBar); homeIcon = (CircledImageView) rootView.findViewById(R.id.homeIcon); homeIcon.bringToFront(); homeIcon.setVisibility(View.INVISIBLE); galleryIcon = (CircledImageView) rootView.findViewById(R.id.galleryIcon); galleryIcon.bringToFront(); galleryIcon.setVisibility(View.INVISIBLE); moreIcon = (CircledImageView) rootView.findViewById(R.id.moreIcon); moreIcon.bringToFront(); } moreIcon.setOnClickListener(onMoreIconClick); return rootView; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (activity.getCastDetailsBundle().size() > 0 && activity.getRestoreMovieDetailsState()) { save = activity.getCastDetailsBundle().get(activity.getCastDetailsBundle().size() - 1); activity.removeCastDetailsBundle(activity.getCastDetailsBundle().size() - 1); if (activity.getSearchViewCount()) activity.decSearchCastDetails(); activity.setRestoreMovieDetailsState(false); } if (save != null && save.getInt("timeOut") == 1) activity.setRestoreMovieDetailsAdapterState(true); // Get the ViewPager and set it's PagerAdapter so that it can display items castDetailsSlideAdapter = new CastDetailsSlideAdapter(getChildFragmentManager(), getResources(), activity); if (mViewPager != null) currPos = mViewPager.getCurrentItem(); mViewPager = (ViewPager) rootView.findViewById(R.id.castDetailsPager); mViewPager.setOffscreenPageLimit(3); mViewPager.setAdapter(castDetailsSlideAdapter); // Give the SlidingTabLayout the ViewPager, this must be done AFTER the ViewPager has had // it's PagerAdapter set. mSlidingTabLayout = (MovieDetailsSlidingTabLayout) rootView.findViewById(R.id.sliding_tabs); mSlidingTabLayout.setViewPager(mViewPager); mSlidingTabLayout.setSelectedIndicatorColors(ContextCompat.getColor(activity, R.color.tabSelected)); mSlidingTabLayout.bringToFront(); } /** * @param savedInstanceState if the fragment is being re-created from a previous saved state, this is the state. */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (save != null) { setTitle(save.getString("title")); currentId = save.getInt("currentId"); timeOut = save.getInt("timeOut"); if (timeOut == 0) { spinner.setVisibility(View.GONE); onOrientationChange(save); } } if (currentId != this.getArguments().getInt("id") || this.timeOut == 1) { currentId = this.getArguments().getInt("id"); moreIcon.setVisibility(View.INVISIBLE); mSlidingTabLayout.setVisibility(View.INVISIBLE); mViewPager.setVisibility(View.INVISIBLE); spinner.setVisibility(View.VISIBLE); request = new JSONAsyncTask(); new Thread(new Runnable() { public void run() { try { request.execute(MovieDB.url + "person/" + currentId + "?append_to_response=combined_credits%2Cimages&api_key=" + MovieDB.key) .get(10000, TimeUnit.MILLISECONDS); } catch (TimeoutException | ExecutionException | InterruptedException | CancellationException e) { request.cancel(true); // we abort the http request, else it will cause problems and slow connection later if (conn != null) conn.disconnect(); if (spinner != null) activity.hideView(spinner); if (getActivity() != null && !(e instanceof CancellationException)) { getActivity().runOnUiThread(new Runnable() { public void run() { Toast.makeText(getActivity(), getResources().getString(R.string.timeout), Toast.LENGTH_SHORT).show(); } }); } setTimeOut(1); } } }).start(); } activity.setTitle(getTitle()); activity.setCastDetailsFragment(this); new Handler().post(new Runnable() { @Override public void run() { castDetailsInfo = (CastDetailsInfo) castDetailsSlideAdapter.getRegisteredFragment(0); castDetailsCredits = (CastDetailsCredits) castDetailsSlideAdapter.getRegisteredFragment(1); castDetailsBiography = (CastDetailsBiography) castDetailsSlideAdapter.getRegisteredFragment(2); } }); showInstantToolbar(); iconMarginConstant = activity.getIconMarginConstant(); iconMarginLandscape = activity.getIconMarginLandscape(); iconConstantSpecialCase = activity.getIconConstantSpecialCase(); twoIcons = activity.getTwoIcons(); twoIconsToolbar = activity.getTwoIconsToolbar(); oneIcon = activity.getOneIcon(); oneIconToolbar = activity.getOneIconToolbar(); Tracker t = ((MovieDB) activity.getApplication()).getTracker(); t.setScreenName("CastDetails - " + getTitle()); t.send(new HitBuilders.ScreenViewBuilder().build()); } /** * This class handles the connection to our backend server. * If the connection is successful we set information on our views. */ class JSONAsyncTask extends AsyncTask<String, Void, Boolean> { /** * Called before doInBackground() */ @Override protected void onPreExecute() { super.onPreExecute(); } /** * Here we establish connection. If everything is ok we update the views. * * @param urls the url to load. * @return true if sucess, false for fail. */ @Override protected Boolean doInBackground(String... urls) { try { URL url = new URL(urls[0]); conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(10000 /* milliseconds */); conn.setConnectTimeout(10000 /* milliseconds */); conn.setRequestMethod("GET"); conn.setDoInput(true); conn.connect(); int status = conn.getResponseCode(); if (status == 200) { BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } br.close(); JSONObject jsonData = new JSONObject(sb.toString()); // is added checks if we are still on the same view, if we don't do this check the program will crash while (castDetailsInfo == null) { Thread.sleep(200); } if (isAdded() && castDetailsInfo != null) { // Name activity.setText(castDetailsInfo.getName(), jsonData.getString("name")); // Profile image if (!jsonData.getString("profile_path").equals("null") && !jsonData.getString("profile_path").isEmpty()) { activity.setBackDropImage(castDetailsInfo.getProfilePath(), jsonData.getString("profile_path")); activity.setImageTag(castDetailsInfo.getProfilePath(), jsonData.getString("profile_path")); } // Birth information begins here. String birthInfoData = ""; if (!jsonData.getString("place_of_birth").equals("null") && !jsonData.getString("place_of_birth").isEmpty()) birthInfoData += jsonData.getString("place_of_birth"); if (!jsonData.getString("birthday").equals("null") && !jsonData.getString("birthday").isEmpty()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US); try { Date date = sdf.parse(jsonData.getString("birthday")); String formattedDate = activity.getDateFormat().format(date); birthInfoData += " " + formattedDate; } catch (java.text.ParseException e) { } } if (!jsonData.getString("deathday").equals("null") && !jsonData.getString("deathday").isEmpty()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US); try { Date date = sdf.parse(jsonData.getString("deathday")); String formattedDate = activity.getDateFormat().format(date); birthInfoData += " - " + formattedDate; } catch (java.text.ParseException e) { } } if (!birthInfoData.equals("null") && !birthInfoData.isEmpty()) activity.setText(castDetailsInfo.getBirthInfo(), birthInfoData); else activity.hideTextView(castDetailsInfo.getBirthInfo()); // Birth information ends here. // Also Known as JSONArray alsoKnownAsArray = jsonData.getJSONArray("also_known_as"); String alsoKnownAsData = ""; for (int i = 0; i < alsoKnownAsArray.length(); i++) { if (i + 1 == alsoKnownAsArray.length()) alsoKnownAsData += alsoKnownAsArray.get(i); else alsoKnownAsData += alsoKnownAsArray.get(i) + ", "; } if (!alsoKnownAsData.equals("null") && !alsoKnownAsData.isEmpty()) activity.setText(castDetailsInfo.getAlsoKnownAs(), getResources().getString(R.string.alsoKnownAs) + " " + alsoKnownAsData); else activity.hideTextView(castDetailsInfo.getAlsoKnownAs()); // Homepage icon if (!jsonData.getString("homepage").isEmpty() && !jsonData.getString("homepage").equals("null")) { homeIconUrl = jsonData.getString("homepage"); homeIconCheck = 0; } else { activity.invisibleView(homeIcon); homeIconCheck = 1; } // Gallery JSONObject galleryObject = jsonData.getJSONObject("images"); JSONArray galleryProfilesArray = galleryObject.getJSONArray("profiles"); galleryList = new ArrayList<>(); if (galleryProfilesArray.length() > 0) { for (int i = 0; i < galleryProfilesArray.length(); i++) { JSONObject object = galleryProfilesArray.getJSONObject(i); galleryList.add(object.getString("file_path")); } galleryIconCheck = 0; } else { activity.invisibleView(galleryIcon); galleryIconCheck = 1; } //Credits, here we load cast JSONObject credits = jsonData.getJSONObject("combined_credits"); JSONArray creditsArray = credits.getJSONArray("cast"); moviesList = new ArrayList<>(); final ArrayList<SimilarModel> similarList = new ArrayList<>(); for (int i = 0; i < creditsArray.length(); i++) { JSONObject object = creditsArray.getJSONObject(i); MovieModel movie = new MovieModel(); movie.setId(object.getInt("id")); if (object.getString("media_type").equals("movie")) { movie.setTitle(object.getString("title")); if (!object.getString("release_date").equals("null") && !object.getString("release_date").isEmpty()) movie.setReleaseDate(object.getString("release_date")); } if (object.getString("media_type").equals("tv")) { movie.setTitle(object.getString("name")); if (!object.getString("first_air_date").equals("null") && !object.getString("first_air_date").isEmpty()) movie.setReleaseDate(object.getString("first_air_date")); } movie.setCharacter(object.getString("character")); // is added checks if we are still on the same view, if we don't do this check the program will crash if (isAdded()) { if (!object.getString("poster_path").equals("null") && !object.getString("poster_path").isEmpty()) movie.setPosterPath( MovieDB.imageUrl + getResources().getString(R.string.imageSize) + object.getString("poster_path")); } movie.setMediaType(object.getString("media_type")); moviesList.add(movie); } // Crew JSONArray crewArray = credits.getJSONArray("crew"); for (int i = 0; i < crewArray.length(); i++) { JSONObject object = crewArray.getJSONObject(i); String departmentAndJob = ""; MovieModel movie = new MovieModel(); movie.setId(object.getInt("id")); if (object.getString("media_type").equals("movie")) { movie.setTitle(object.getString("title")); if (!object.getString("release_date").equals("null") && !object.getString("release_date").isEmpty()) movie.setReleaseDate(object.getString("release_date")); } if (object.getString("media_type").equals("tv")) { movie.setTitle(object.getString("name")); if (!object.getString("first_air_date").equals("null") && !object.getString("first_air_date").isEmpty()) movie.setReleaseDate(object.getString("first_air_date")); } // is added checks if we are still on the same view, if we don't do this check the program will crash if (isAdded()) { if (!object.getString("poster_path").equals("null") && !object.getString("poster_path").isEmpty()) movie.setPosterPath( MovieDB.imageUrl + getResources().getString(R.string.imageSize) + object.getString("poster_path")); } if (!object.getString("department").equals("null") && !object.getString("department").isEmpty()) departmentAndJob += object.getString("department"); if (!object.getString("job").equals("null") && !object.getString("job").isEmpty()) departmentAndJob += " / " + object.getString("job"); movie.setDepartmentAndJob(departmentAndJob); movie.setMediaType(object.getString("media_type")); moviesList.add(movie); } Collections.sort(moviesList, movieModel); ArrayList<MovieModel> movieListNoDuplicates = removeDuplicates(moviesList); int simLen = 6; if (movieListNoDuplicates.size() < 6) simLen = movieListNoDuplicates.size(); for (int i = 0; i < simLen; i++) { SimilarModel simMov = new SimilarModel(); simMov.setId(movieListNoDuplicates.get(i).getId()); simMov.setMediaType(movieListNoDuplicates.get(i).getMediaType()); simMov.setTitle(movieListNoDuplicates.get(i).getTitle()); if (movieListNoDuplicates.get(i).getReleaseDate() != null) simMov.setReleaseDate(movieListNoDuplicates.get(i).getReleaseDate()); // is added checks if we are still on the same view, if we don't do this check the program will crash if (isAdded()) { if (movieListNoDuplicates.get(i).getPosterPath() != null) simMov.setPosterPath( MovieDB.imageUrl + getResources().getString(R.string.imageSize) + movieListNoDuplicates.get(i).getPosterPath()); } similarList.add(simMov); } if (similarList.size() == 0) activity.hideView(castDetailsInfo.getKnownHolder()); if (movieListNoDuplicates.size() < 7) activity.hideView(castDetailsInfo.getShowMoreButton()); activity.runOnUiThread(new Runnable() { @Override public void run() { if (moviesList.size() == 0) { noCredits = true; mSlidingTabLayout.disableTabClickListener(1); } // Cast if (isAdded()) { castDetailsInfo.setKnownList(similarList); castDetailsCredits.setAdapter(moviesList); } } }); // Biography final String biography = jsonData.getString("biography"); if (!biography.equals("null") && !biography.isEmpty()) activity.setText(castDetailsBiography.getBiography(), biography); else activity.setText(castDetailsBiography.getBiography(), getResources().getString(R.string.noBiography)); return true; } } } catch (ParseException | IOException | JSONException e) { if (conn != null) conn.disconnect(); } catch (InterruptedException e) { } finally { if (conn != null) conn.disconnect(); } return false; } /** * Fired after doInBackground() has finished * * @param result true if connection is successful, false if connection has failed. */ protected void onPostExecute(Boolean result) { // is added checks if we are still on the same view, if we don't do this check the program will cra if (isAdded()) { if (!result) { Toast.makeText(getActivity(), R.string.noConnection, Toast.LENGTH_LONG).show(); setTimeOut(1); spinner.setVisibility(View.GONE); mViewPager.setVisibility(View.GONE); } else { setTimeOut(0); currPos = 0; mViewPager.setCurrentItem(0); spinner.setVisibility(View.GONE); mSlidingTabLayout.setVisibility(View.VISIBLE); mViewPager.setVisibility(View.VISIBLE); mSlidingTabLayout.setOnPageChangeListener(onPageChangeSelected); if (homeIconCheck == 1 && galleryIconCheck == 1) { moreIconCheck = 1; activity.hideView(moreIcon); activity.hideView(castDetailsInfo.getMoreIcon()); } else { moreIconCheck = 0; activity.showView(castDetailsInfo.getMoreIcon()); // set listener on backdrop click to open gallery if (galleryIconCheck == 0) castDetailsInfo.getProfilePath().setOnClickListener(onGalleryIconClick); adjustIconsPos(homeIcon, galleryIcon); adjustIconsPos(castDetailsInfo.getHomeIcon(), castDetailsInfo.getGalleryIcon()); } } } else setTimeOut(1); } } /** * We use this key to know if the user has tried to open this movie and the connection failed. * So if he tries to load again the same movie we know that the connection has failed and we need to make a new request. */ public int getTimeOut() { return timeOut; } /** * Updates the timeOut value. */ public void setTimeOut(int timeOut) { this.timeOut = timeOut; } /** * Update the title. We use this method to save our title and then to set it on the Toolbar. */ public void setTitle(String title) { this.title = title; } /** * Get the title. */ private String getTitle() { return this.title; } /** * Called to ask the fragment to save its current dynamic state, * so it can later be reconstructed in a new instance of its process is restarted. * * @param outState Bundle in which to place your saved state. */ @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // Used to avoid bug where we add item in the back stack // and if we change orientation twice the item from the back stack has null values if (save != null && save.getInt("timeOut") == 1) save = null; if (save != null) { outState.putBundle("save", save); if (addToBackStack) { activity.addCastDetailsBundle(save); addToBackStack = false; } } else { Bundle send = new Bundle(); send.putInt("currentId", currentId); if (request != null && request.getStatus() == AsyncTask.Status.RUNNING) { timeOut = 1; request.cancel(true); } send.putInt("timeOut", timeOut); send.putString("title", title); if (timeOut == 0) { // HomePage send.putInt("homeIconCheck", homeIconCheck); if (homeIconCheck == 0) send.putString("homepage", homeIconUrl); // Gallery icon send.putInt("galleryIconCheck", galleryIconCheck); if (galleryIconCheck == 0) send.putStringArrayList("galleryList", galleryList); // More icon send.putInt("moreIconCheck", moreIconCheck); // Cast details info begins here if (castDetailsInfo != null) { // Name send.putString("name", castDetailsInfo.getName().getText().toString()); // Poster path url if (castDetailsInfo.getProfilePath().getTag() != null) send.putString("profilePathURL", castDetailsInfo.getProfilePath().getTag().toString()); // Birth info send.putString("birthInfo", castDetailsInfo.getBirthInfo().getText().toString()); // Also known as send.putString("alsoKnownAs", castDetailsInfo.getAlsoKnownAs().getText().toString()); // Known list if (castDetailsInfo.getKnownList() != null && castDetailsInfo.getKnownList().size() > 0) send.putParcelableArrayList("knownList", castDetailsInfo.getKnownList()); } // Cast details info ends here // Credits starts here if (castDetailsCredits != null) send.putParcelableArrayList("moviesList", moviesList); // Credits ends here // Overview if (castDetailsBiography != null) send.putString("biography", castDetailsBiography.getBiography().getText().toString()); } outState.putBundle("save", send); save = send; if (addToBackStack) { activity.addCastDetailsBundle(send); addToBackStack = false; } } } /** * Fired when are restoring from backState or orientation has changed. * * @param args our bundle with saved state. */ private void onOrientationChange(Bundle args) { // Home page homeIconCheck = args.getInt("homeIconCheck"); if (homeIconCheck == 0) homeIconUrl = args.getString("homepage"); // Gallery galleryIconCheck = args.getInt("galleryIconCheck"); if (galleryIconCheck == 0) { galleryList = new ArrayList<>(); galleryList = args.getStringArrayList("galleryList"); if (galleryList.size() == 0) activity.hideView(galleryIcon); } // More icon moreIconCheck = args.getInt("moreIconCheck"); if (homeIconCheck == 1 && galleryIconCheck == 1) { moreIconCheck = 1; moreIcon.setVisibility(View.GONE); } else moreIconCheck = 0; mSlidingTabLayout.setOnPageChangeListener(onPageChangeSelected); activity.setCastDetailsInfoBundle(save); activity.setCastDetailsCreditsBundle(save); activity.setCastDetailsBiographyBundle(save); moviesList = save.getParcelableArrayList("moviesList"); if (moviesList != null && moviesList.size() == 0) { noCredits = true; mSlidingTabLayout.disableTabClickListener(1); } new Handler().post(new Runnable() { @Override public void run() { castDetailsInfo = (CastDetailsInfo) castDetailsSlideAdapter.getRegisteredFragment(0); castDetailsCredits = (CastDetailsCredits) castDetailsSlideAdapter.getRegisteredFragment(1); if (currPos == 0) { moreIcon.setVisibility(View.INVISIBLE); } else if (moreIconCheck == 0) { castDetailsInfo.getMoreIcon().setVisibility(View.INVISIBLE); updateDownPos(); } if (moreIconCheck == 1) castDetailsInfo.getMoreIcon().setVisibility(View.GONE); else { // set listener on backdrop click to open gallery if (galleryIconCheck == 0 && galleryList.size() > 0) castDetailsInfo.getProfilePath().setOnClickListener(onGalleryIconClick); adjustIconsPos(homeIcon, galleryIcon); adjustIconsPos(castDetailsInfo.getHomeIcon(), castDetailsInfo.getGalleryIcon()); } // disable orientation changing, enable nav drawer sliding, show toolbar if (galleryIconCheck == 0 && galleryList.size() == 1) { activity.getWindow().getDecorView().setBackgroundColor( ContextCompat.getColor(activity, R.color.background_material_light)); if (activity.getSupportActionBar() != null) activity.getSupportActionBar().show(); activity.getMDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); if (Build.VERSION.SDK_INT >= 19) activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); // Check orientation and lock to portrait if we are on phone if (getResources().getBoolean(R.bool.portrait_only)) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } if (castDetailsCredits.getMoviesList().size() < 7) activity.hideView(castDetailsInfo.getShowMoreButton()); } }); } /** * Class which listens when the user has tapped on More icon button. */ public class onMoreIconClick implements View.OnClickListener { private boolean key; private boolean toolbarHidden; private int items; private View toolbarView = activity.findViewById(R.id.toolbar); private int currScroll; public onMoreIconClick() { // keep references for your onClick logic } public boolean getKey() { return key; } public void setKey(boolean key) { this.key = key; } @Override public void onClick(View v) { items = homeIconCheck + galleryIconCheck; toolbarHidden = toolbarView.getTranslationY() == -toolbarView.getHeight(); currScroll = castDetailsInfo.getRootView().getScrollY(); if (!key) { iconDirection = 1; if (currPos == 0) { // 2 icons if (items == 0) { if (toolbarHidden && currScroll / scale > twoIcons) { iconDirection = -1; } else if (!toolbarHidden && currScroll / scale > twoIconsToolbar) { iconDirection = -1; } } // 1 icon if (items == 1) { if (toolbarHidden && currScroll / scale > oneIcon) { iconDirection = -1; } else if (!toolbarHidden && currScroll / scale > oneIconToolbar) { iconDirection = -1; } } } if (currPos == 0) { castDetailsInfo.getMoreIcon() .setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_close_white_36dp)); showHideImages(View.VISIBLE, castDetailsInfo.getHomeIcon(), castDetailsInfo.getGalleryIcon()); } else { moreIcon.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_close_white_36dp)); showHideImages(View.VISIBLE, homeIcon, galleryIcon); } key = true; } else { if (currPos == 0) { castDetailsInfo.getMoreIcon().setImageDrawable( ContextCompat.getDrawable(activity, R.drawable.ic_more_vert_white_36dp)); showHideImages(View.INVISIBLE, castDetailsInfo.getHomeIcon(), castDetailsInfo.getGalleryIcon()); } else { moreIcon.setImageDrawable( ContextCompat.getDrawable(activity, R.drawable.ic_more_vert_white_36dp)); showHideImages(View.INVISIBLE, homeIcon, galleryIcon); } key = false; } } } /** * Class which listens when the user has tapped on Home icon button. */ public class onHomeIconClick implements View.OnClickListener { public onHomeIconClick() { // keep references for your onClick logic } @Override public void onClick(View v) { Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(homeIcon.getTag().toString())); startActivity(i); } } /** * Class which listens when the user has tapped on Gallery icon button. */ public class onGalleryIconClick implements View.OnClickListener { public onGalleryIconClick() { // keep references for your onClick logic } @Override public void onClick(View v) { if (activity.getSearchViewCount()) activity.incSearchCastDetails(); if (galleryList.size() == 1) { setAddToBackStack(true); onSaveInstanceState(new Bundle()); if (activity.getSupportActionBar() != null) activity.getSupportActionBar().hide(); activity.getWindow().getDecorView() .setBackgroundColor(ContextCompat.getColor(activity, R.color.black)); FragmentManager manager = getFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.replace(R.id.frame_container, GalleryPreviewDetail.newInstance(MovieDB.imageUrl + getResources().getString(R.string.galleryPreviewImgSize) + galleryList.get(0))); // add the current transaction to the back stack: transaction.addToBackStack("movieDetails"); transaction.commit(); } else { try { setAddToBackStack(true); onSaveInstanceState(new Bundle()); showInstantToolbar(); activity.getGalleryListView().setTitle(getTitle()); FragmentManager manager = getFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); Bundle args = new Bundle(); args.putStringArrayList("galleryList", galleryList); activity.getGalleryListView().setArguments(args); transaction.replace(R.id.frame_container, activity.getGalleryListView()); // add the current transaction to the back stack: transaction.addToBackStack("movieDetails"); transaction.commit(); } catch (java.lang.IllegalStateException e) { GalleryList galleryListView = new GalleryList(); galleryListView.setTitle(getTitle()); FragmentManager manager = getFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); Bundle args = new Bundle(); args.putStringArrayList("galleryList", galleryList); galleryListView.setArguments(args); transaction.replace(R.id.frame_container, galleryListView); // add the current transaction to the back stack: transaction.addToBackStack("movieDetails"); transaction.commit(); } } } } /** * Class which listens when the user has changed the tap in Cast details */ public class onPageChangeSelected implements ViewPager.OnPageChangeListener { private boolean toolbarHidden; private View toolbarView = activity.findViewById(R.id.toolbar); @Override public void onPageScrollStateChanged(int state) { } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (noCredits) { if (position == 1 && currPos == 2) { mViewPager.setCurrentItem(0); return; } if (position == 1 && currPos == 0) { mViewPager.setCurrentItem(2); return; } } if (toolbarView != null) toolbarHidden = toolbarView.getTranslationY() == -toolbarView.getHeight(); if (position == 0) { scrollSpeed = 2.2F; if (castDetailsInfo != null) { if (119 * scale <= (castDetailsInfo.getScrollView().getChildAt(0).getHeight() - (567 * scale)) && castDetailsInfo.canScroll()) { if (toolbarHidden) { final ObservableParallaxScrollView scrollView = castDetailsInfo.getScrollView(); if (scrollView.getCurrentScrollY() / scale < 119) { infoTabScrollPosUpdated = true; scrollView.post(new Runnable() { @Override public void run() { scrollView.scrollTo(0, (int) (119 * scale)); } }); } } } else showInstantToolbar(); } } else scrollSpeed = 1; if (position == 1 && castDetailsCredits != null) { if (castDetailsCredits.getMoviesList() != null && castDetailsCredits.getMoviesList().size() > 0) { final AbsListView listView = castDetailsCredits.getListView(); if (castDetailsCredits.canScroll()) { listView.post(new Runnable() { @Override public void run() { if (toolbarHidden && ((Scrollable) listView).getCurrentScrollY() < minThreshold) { if (phone) listView.smoothScrollBy((int) (56 * scale), 0); else listView.smoothScrollBy((int) (65 * scale), 0); } } }); } else { if (toolbarHidden) showInstantToolbar(); } } else { if (toolbarHidden) showInstantToolbar(); } } if (position == 2 && castDetailsBiography != null) { castDetailsBiography.getScrollView().post(new Runnable() { @Override public void run() { if (toolbarHidden) castDetailsBiography.getScrollView().scrollTo(0, (int) (56 * scale)); else castDetailsBiography.getScrollView().scrollTo(0, 0); } }); } if (moreIconCheck == 0) { if (castDetailsInfo != null) { castDetailsInfoScrollY = castDetailsInfo.getRootView().getScrollY(); galleryIcon.clearAnimation(); homeIcon.clearAnimation(); homeIcon.setVisibility(View.INVISIBLE); castDetailsInfo.getHomeIcon().setVisibility(View.INVISIBLE); galleryIcon.setVisibility(View.INVISIBLE); castDetailsInfo.getGalleryIcon().setVisibility(View.INVISIBLE); moreIcon.setImageDrawable( ContextCompat.getDrawable(activity, R.drawable.ic_more_vert_white_36dp)); if (position == 0) { castDetailsInfo.getMoreIcon().setImageDrawable( ContextCompat.getDrawable(activity, R.drawable.ic_more_vert_white_36dp)); moreIcon.setVisibility(View.INVISIBLE); } else { castDetailsInfo.getMoreIcon().setVisibility(View.INVISIBLE); } onMoreIconClick.setKey(false); if (currPos == 0 && position == 1) { updateUpPos(); createDownAnimation(); moreIcon.startAnimation(downAnimation); } if (currPos == 0 && position == 2) { updateUpPos(); createDownAnimation(); moreIcon.startAnimation(downAnimation); } if (currPos == 1 && position == 0) { updateDownPos(); // we have a special case here if this is true, this means that we have been in the cast tab // we have hidden the toolbar and we are returning to the info tab where the scrollY was 0 // so earlier in this function we updated the scrollY value and now we need to update the // animation value else the icon will "jump" if (infoTabScrollPosUpdated) { infoTabScrollPosUpdated = false; createUpAnimation((119 * scale) - castDetailsInfo.getScrollView().getCurrentScrollY()); } else createUpAnimation(0); moreIcon.startAnimation(upAnimation); } if (currPos == 2 && position == 0) { updateDownPos(); if (infoTabScrollPosUpdated) { infoTabScrollPosUpdated = false; createUpAnimation((119 * scale) - castDetailsInfo.getScrollView().getCurrentScrollY()); } else createUpAnimation(0); moreIcon.startAnimation(upAnimation); } } } if (!noCredits || position != 1) currPos = position; } } /** * Listener which updates the icons position after the animation ended. */ private class DownAnimationListener implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation animation) { moreIcon.clearAnimation(); updateDownPos(); moreIcon.setVisibility(View.VISIBLE); RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) moreIcon.getLayoutParams(); layoutParams.width = RelativeLayout.LayoutParams.WRAP_CONTENT; layoutParams.height = RelativeLayout.LayoutParams.WRAP_CONTENT; moreIcon.setLayoutParams(layoutParams); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } } /** * Updates the icons position when called. */ public void updateDownPos() { RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(moreIcon.getWidth(), moreIcon.getHeight()); RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(homeIcon.getWidth(), homeIcon.getHeight()); RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(galleryIcon.getWidth(), galleryIcon.getHeight()); lp.addRule(RelativeLayout.ALIGN_PARENT_END); lp1.addRule(RelativeLayout.ALIGN_PARENT_END); lp2.addRule(RelativeLayout.ALIGN_PARENT_END); lp.setMargins(0, (int) (scale * (496 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 15 + 0.5f), 0); moreIcon.setLayoutParams(lp); lp1.setMargins(0, (int) (scale * (439 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); homeIcon.setLayoutParams(lp1); lp2.setMargins(0, (int) (scale * (383.3 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); galleryIcon.setLayoutParams(lp2); } /** * Listener which updates the icons position after the animation ended. */ private class UpAnimationListener implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation animation) { castDetailsInfo.getMoreIcon().clearAnimation(); castDetailsInfo.getMoreIcon().setVisibility(View.VISIBLE); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } } /** * Updates the icons position when called. */ public void updateUpPos() { RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(moreIcon.getWidth(), moreIcon.getHeight()); RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(homeIcon.getWidth(), homeIcon.getHeight()); RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(galleryIcon.getWidth(), galleryIcon.getHeight()); lp.addRule(RelativeLayout.ALIGN_PARENT_END); lp1.addRule(RelativeLayout.ALIGN_PARENT_END); lp2.addRule(RelativeLayout.ALIGN_PARENT_END); lp.setMargins(0, (int) (scale * (346 + iconMarginConstant) + 0.5f - castDetailsInfoScrollY), (int) (scale * 15 + 0.5f), 0); moreIcon.setLayoutParams(lp); } /** * Creates animation for the More Icon with down direction. */ public void createDownAnimation() { // if this is 300 this means that we are on tablet and orientation is landscape // we do this else the animation will go off screen // so if we are on landscape we change the direction of the animation if (iconMarginLandscape == 300) downAnimation = new TranslateAnimation(0, 0, 0, -scale * 150 + 0.5f + castDetailsInfoScrollY); else downAnimation = new TranslateAnimation(0, 0, 0, scale * (150 + iconConstantSpecialCase) + 0.5f + castDetailsInfoScrollY); downAnimation.setDuration(500); downAnimation.setFillAfter(false); downAnimation.setAnimationListener(downAnimationListener); } /** * Creates animation for the More Icon with up direction. */ public void createUpAnimation(float dy) { // if this is 300 this means that we are on tablet and orientation is landscape // we do this else the animation will go off screen // so if we are on landscape we change the direction of the animation if (iconMarginLandscape == 300) upAnimation = new TranslateAnimation(0, 0, 0, scale * 150 + 0.5f - castDetailsInfoScrollY - dy); else upAnimation = new TranslateAnimation(0, 0, 0, -scale * (150 + iconConstantSpecialCase) + 0.5f - castDetailsInfoScrollY - dy); upAnimation.setDuration(500); upAnimation.setFillAfter(false); upAnimation.setAnimationListener(upAnimationListener); } public CastDetails.onMoreIconClick getOnMoreIconClick() { return onMoreIconClick; } public void setAddToBackStack(boolean addToBackStack) { this.addToBackStack = addToBackStack; } public Bundle getSave() { return save; } public void setSave(Bundle save) { this.save = save; } /** * This method calculates what icons do we have. * * @param homeIcon the first icon * @param galleryIcon the second icon */ public void adjustIconsPos(CircledImageView homeIcon, CircledImageView galleryIcon) { int iconCount[] = { homeIconCheck, galleryIconCheck }; ArrayList<CircledImageView> circledImageViews = new ArrayList<>(); circledImageViews.add(homeIcon); circledImageViews.add(galleryIcon); for (int i = 0; i < iconCount.length; i++) { if (iconCount[i] == 1) circledImageViews.get(circledImageViews.size() - 1).setVisibility(View.INVISIBLE); else { CircledImageView temp = circledImageViews.get(0); switch (i) { case 0: temp.setOnClickListener(onHomeIconClick); temp.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_home_white_24dp)); temp.setTag(homeIconUrl); break; case 1: temp.setOnClickListener(onGalleryIconClick); temp.setImageDrawable( ContextCompat.getDrawable(activity, R.drawable.ic_photo_camera_white_24dp)); break; } circledImageViews.remove(0); } } } /** * Fired from the on More Icon click listeners. Updates the visibility of the gallery and homePage icon. * And creates animation for them also. * * @param visibility visibility value * @param homeIcon first icon * @param galleryIcon second icon */ public void showHideImages(int visibility, CircledImageView homeIcon, CircledImageView galleryIcon) { float dy[] = { 0.7f, 56.7f }; float infoTabDy[] = { -2.4f, 53.5f }; int currDy = 0; int delay = 100; int iconCount[] = { homeIconCheck, galleryIconCheck }; ArrayList<CircledImageView> circledImageViews = new ArrayList<>(); circledImageViews.add(homeIcon); circledImageViews.add(galleryIcon); if (visibility == View.VISIBLE) { if (currPos != 0) updateIconDownPos(); else updateIconDownPosInInfoTab(); } else { if (currPos != 0) updateIconUpPos(); else updateIconUpPosInInfoTab(); } for (int i = 0; i < iconCount.length; i++) { if (iconCount[i] == 1) circledImageViews.get(circledImageViews.size() - 1).setVisibility(View.INVISIBLE); else { CircledImageView temp = circledImageViews.get(0); if (visibility == View.VISIBLE) { if (currPos == 0) createIconUpAnimation(infoTabDy[currDy], delay); else createIconUpAnimation(dy[currDy], delay); temp.startAnimation(iconUpAnimation); } else { if (currPos == 0) createIconDownAnimation(infoTabDy[currDy]); else createIconDownAnimation(dy[currDy]); temp.startAnimation(iconDownAnimation); } currDy++; delay -= 50; temp.setVisibility(visibility); circledImageViews.remove(0); } } } /** * Creates animation for the gallery and homePage Icons with up direction. */ public void createIconUpAnimation(float dy, int delay) { iconUpAnimation = new TranslateAnimation(0, 0, 0, (-(scale * 67.3f) + 0.5f - (dy * scale)) * iconDirection); iconUpAnimation.setDuration(250); iconUpAnimation.setFillAfter(false); iconUpAnimation.setStartOffset(delay); iconUpAnimation.setAnimationListener(iconUpAnimationListener); } /** * Creates animation for the gallery and homePage Icons with down direction. */ public void createIconDownAnimation(float dy) { iconDownAnimation = new TranslateAnimation(0, 0, 0, ((scale * 67.3f) + 0.5f + (dy * scale)) * iconDirection); iconDownAnimation.setDuration(250); iconDownAnimation.setFillAfter(false); iconDownAnimation.setAnimationListener(iconDownAnimationListener); } /** * Listener which updates the icons position after the animation ended. */ private class IconUpAnimationListener implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation animation) { if (currPos != 0) { updateIconUpPos(); homeIcon.clearAnimation(); galleryIcon.clearAnimation(); } else { updateIconUpPosInInfoTab(); castDetailsInfo.getHomeIcon().clearAnimation(); castDetailsInfo.getGalleryIcon().clearAnimation(); } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } } /** * Listener which updates the icons position after the animation ended. */ private class IconDownAnimationListener implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation animation) { if (currPos != 0) { updateIconDownPos(); homeIcon.clearAnimation(); galleryIcon.clearAnimation(); } else { updateIconDownPosInInfoTab(); castDetailsInfo.getHomeIcon().clearAnimation(); castDetailsInfo.getGalleryIcon().clearAnimation(); } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } } /** * Updates the icons position when called. */ public void updateIconDownPos() { RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(homeIcon.getWidth(), homeIcon.getHeight()); RelativeLayout.LayoutParams lp3 = new RelativeLayout.LayoutParams(galleryIcon.getWidth(), galleryIcon.getHeight()); lp1.addRule(RelativeLayout.ALIGN_PARENT_END); lp3.addRule(RelativeLayout.ALIGN_PARENT_END); lp1.setMargins(0, (int) (scale * (506 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); homeIcon.setLayoutParams(lp1); lp3.setMargins(0, (int) (scale * (506 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); galleryIcon.setLayoutParams(lp3); } /** * Updates the icons position when called. */ public void updateIconUpPos() { RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(homeIcon.getWidth(), homeIcon.getHeight()); RelativeLayout.LayoutParams lp3 = new RelativeLayout.LayoutParams(galleryIcon.getWidth(), galleryIcon.getHeight()); lp1.addRule(RelativeLayout.ALIGN_PARENT_END); lp3.addRule(RelativeLayout.ALIGN_PARENT_END); lp1.setMargins(0, (int) (scale * (439 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); homeIcon.setLayoutParams(lp1); lp3.setMargins(0, (int) (scale * (383.3 + iconMarginConstant - iconMarginLandscape + iconConstantSpecialCase) + 0.5f), (int) (scale * 23 + 0.5f), 0); galleryIcon.setLayoutParams(lp3); } /** * Updates the icons position in the movie info tap when called. */ public void updateIconDownPosInInfoTab() { RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) castDetailsInfo.getGalleryIcon() .getLayoutParams(); p.removeRule(RelativeLayout.ABOVE); p.removeRule(RelativeLayout.BELOW); p.addRule(RelativeLayout.ABOVE, R.id.moreIcon); p.setMargins(0, 0, (int) (23 * scale), (int) (-20 * scale)); castDetailsInfo.getGalleryIcon().setLayoutParams(p); castDetailsInfo.getHomeIcon().setLayoutParams(p); } /** * Updates the icons position in the movie info tap when called. */ public void updateIconUpPosInInfoTab() { RelativeLayout.LayoutParams p3 = new RelativeLayout.LayoutParams(homeIcon.getWidth(), homeIcon.getHeight()); RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(galleryIcon.getWidth(), galleryIcon.getHeight()); p3.addRule(RelativeLayout.ALIGN_PARENT_END); p.addRule(RelativeLayout.ALIGN_PARENT_END); if (iconDirection == 1) { p3.addRule(RelativeLayout.ABOVE, R.id.moreIcon); p3.setMargins(0, 0, (int) (23 * scale), (int) (44 * scale)); p.addRule(RelativeLayout.ABOVE, R.id.homeIcon); p.setMargins(0, 0, (int) (23 * scale), (int) (15.5f * scale)); } else { p3.addRule(RelativeLayout.BELOW, R.id.moreIcon); p3.setMargins(0, (int) (16 * scale), (int) (23 * scale), 0); p.addRule(RelativeLayout.BELOW, R.id.homeIcon); p.setMargins(0, (int) (15.5f * scale), (int) (23 * scale), 0); } castDetailsInfo.getHomeIcon().setLayoutParams(p3); castDetailsInfo.getGalleryIcon().setLayoutParams(p); } @Override public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) { float scroll = scrollY; if (mViewPager.getCurrentItem() == 0) { scroll = (scroll / scrollSpeed); if (scrollY / scale >= 0 && onMoreIconClick.getKey()) onMoreIconClick.onClick(null); } if (dragging) { View toolbarView = getActivity().findViewById(R.id.toolbar); if (scroll > oldScrollY) { if (upDyKey) { upDy = scroll; upDyKey = false; } else { dy = upDy - scroll; if (dy >= -toolbarView.getHeight()) { toolbarView.setTranslationY(dy); mSlidingTabLayout.setTranslationY(dy); } else { toolbarView.setTranslationY(-toolbarView.getHeight()); mSlidingTabLayout.setTranslationY(-toolbarView.getHeight()); } downDyKey = true; } } if (scroll < oldScrollY) { if (downDyKey) { downDy = scroll; downDyTrans = toolbarView.getTranslationY(); downDyKey = false; } else { dy = (downDyTrans + (downDy - scroll)); if (dy <= 0) { toolbarView.setTranslationY(dy); mSlidingTabLayout.setTranslationY(dy); } else { toolbarView.setTranslationY(0); mSlidingTabLayout.setTranslationY(0); } upDyKey = true; } } } oldScrollY = scroll; } @Override public void onDownMotionEvent() { } @Override public void onUpOrCancelMotionEvent(ScrollState scrollState) { adjustToolbar(scrollState); } private Scrollable getCurrentScrollable() { Fragment fragment = getCurrentFragment(); if (fragment == null) { return null; } View view = fragment.getView(); if (view == null) { return null; } switch (mViewPager.getCurrentItem()) { case 0: return (Scrollable) view.findViewById(R.id.castdetailsinfo); case 1: return (Scrollable) view.findViewById(R.id.castdetailscredits); case 2: return (Scrollable) view.findViewById(R.id.castdetailsbiography); default: return (Scrollable) view.findViewById(R.id.castdetailsinfo); } } /** * Fixes the position of the toolbar * * @param scrollState */ private void adjustToolbar(ScrollState scrollState) { View toolbarView = getActivity().findViewById(R.id.toolbar); int toolbarHeight = toolbarView.getHeight(); final Scrollable scrollable = getCurrentScrollable(); if (scrollable == null) { return; } int scrollY = scrollable.getCurrentScrollY(); if (scrollState == ScrollState.DOWN) { showToolbar(); } else if (scrollState == ScrollState.UP) { switch (currPos) { case 0: if (119 * scale <= scrollY) { hideToolbar(); } else { showToolbar(); } break; case 1: if (toolbarHeight <= scrollY - hideThreshold) { hideToolbar(); } else { showToolbar(); } break; case 2: if (toolbarHeight <= scrollY) { hideToolbar(); } else { showToolbar(); } break; } } } /** * Returns the current active fragment for the given position */ private Fragment getCurrentFragment() { return castDetailsSlideAdapter.getRegisteredFragment(mViewPager.getCurrentItem()); } private void showToolbar() { animateToolbar(0); } private void hideToolbar() { View toolbarView = getActivity().findViewById(R.id.toolbar); animateToolbar(-toolbarView.getHeight()); } /** * Animates our toolbar to the given direction * * @param toY our translation length. */ private void animateToolbar(final float toY) { if (activity != null) { View toolbarView = activity.findViewById(R.id.toolbar); if (toolbarView != null) { toolbarView.animate().translationY(toY).setInterpolator(new DecelerateInterpolator(2)) .setDuration(200).start(); mSlidingTabLayout.animate().translationY(toY).setInterpolator(new DecelerateInterpolator(2)) .setDuration(200).start(); if (toY == 0) { upDyKey = true; downDyKey = false; downDy = 9999999; } else { downDyKey = true; upDyKey = false; upDy = -9999999; } } } } /** * Instant shows our toolbar. Used when click on movie details from movies list and toolbar is hidden. */ public void showInstantToolbar() { if (activity != null) { View toolbarView = activity.findViewById(R.id.toolbar); if (toolbarView != null) { toolbarView.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).setDuration(0) .start(); mSlidingTabLayout.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)) .setDuration(0).start(); upDyKey = true; downDyKey = false; downDy = 9999999; } } } public ViewPager getmViewPager() { return mViewPager; } private ArrayList<MovieModel> removeDuplicates(List<MovieModel> l) { Set<MovieModel> set = new TreeSet<>(new Comparator<MovieModel>() { @Override public int compare(MovieModel o1, MovieModel o2) { if (o1.getId() == o2.getId()) return 0; else return 1; } }); set.addAll(l); ArrayList<MovieModel> movieListWithoutDuplicates = new ArrayList<>(); movieListWithoutDuplicates.addAll(set); return movieListWithoutDuplicates; } /** * Fired when fragment is destroyed. */ public void onDestroyView() { super.onDestroyView(); onPageChangeSelected = null; onGalleryIconClick = null; onMoreIconClick = null; onHomeIconClick = null; onPageChangeSelected = null; downAnimationListener = null; upAnimationListener = null; iconUpAnimationListener = null; iconDownAnimationListener = null; movieModel = null; } }