Java tutorial
/* * Copyright 2014 Nicholas Liu * * 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 ca.zadrox.dota2esportticker.ui; import android.animation.Animator; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.LoaderManager; import android.content.Context; import android.content.Intent; import android.content.Loader; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import java.util.ArrayList; import ca.zadrox.dota2esportticker.R; import ca.zadrox.dota2esportticker.data.MatchContract; import ca.zadrox.dota2esportticker.data.http.team.model.Team; import ca.zadrox.dota2esportticker.ui.widget.BezelImageView; import ca.zadrox.dota2esportticker.ui.widget.ObservableScrollView; import ca.zadrox.dota2esportticker.ui.widget.SlidingTabLayout; import ca.zadrox.dota2esportticker.util.TeamDetailLoader; import ca.zadrox.dota2esportticker.util.UIUtils; /** * Created by Acco on 12/9/2014. */ public class TeamDetailActivity extends BaseActivity implements ObservableScrollView.Callbacks { private static final String TAG = TeamDetailActivity.class.getSimpleName(); public static final String STATUS_LOAD_COMPLETE = "ca.zadrox.dota2esportticker.action.STATUS_LOAD_COMPLETE"; private Handler mHandler = new Handler(); private ViewPager mViewPager; private SlidingTabLayout mSlidingTabLayout; private Context mContext = this; private static final int GGLOADER_ID = 0; private static final int ULOADER_ID = 1; private static final int RLOADER_ID = 2; private static final String[] UPCOMING_PROJECTION = { MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry._ID, MatchContract.SeriesEntry.COLUMN_DATETIME, MatchContract.SeriesEntry.COLUMN_BEST_OF, MatchContract.SeriesEntry.COLUMN_TEAM_ONE_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TEAM_ONE_FLAG, MatchContract.SeriesEntry.COLUMN_TEAM_TWO_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TEAM_TWO_FLAG, MatchContract.SeriesEntry.COLUMN_TOURNAMENT_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TOURNAMENT_LOGO, MatchContract.SeriesEntry.COLUMN_TOURNAMENT_URL, MatchContract.SeriesEntry.COLUMN_GG_MATCH_PAGE, MatchContract.ReminderEntry.COLUMN_SET_REMINDER }; private static final String[] RESULT_PROJECTION = { MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry._ID, MatchContract.SeriesEntry.COLUMN_DATETIME, MatchContract.SeriesEntry.COLUMN_BEST_OF, MatchContract.SeriesEntry.COLUMN_TEAM_ONE_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TEAM_ONE_FLAG, MatchContract.SeriesEntry.COLUMN_TEAM_TWO_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TEAM_TWO_FLAG, MatchContract.SeriesEntry.COLUMN_TOURNAMENT_NAME, MatchContract.SeriesEntry.COLUMN_PATH_TOURNAMENT_LOGO, MatchContract.SeriesEntry.COLUMN_GG_MATCH_PAGE, MatchContract.ResultEntry.COLUMN_TEAM_ONE_SCORE, MatchContract.ResultEntry.COLUMN_TEAM_TWO_SCORE }; private Team mTeam; private String teamName; public static final String EXTRA_TEAM_URL = "extra_team_url"; private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { recomputeScrollingConstants(); } }; private ObservableScrollView mScrollView; private View mScrollViewChild; private int mMaxHeaderElevation; private FrameLayout mHeaderBox; private TextView mHeaderTeamName; private BezelImageView mHeaderTeamLogo; private int mHeaderHeightPixels; private float mHeaderTextXTranslation; private int mHeaderOffset; private ArrayList<Runnable> mDeferredUiOperations = new ArrayList<>(); private LinearLayout mDetailsContainer; public static Intent createIntent(Context context, String url) { Intent intent = new Intent(context, TeamDetailActivity.class); intent.putExtra(EXTRA_TEAM_URL, url); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_team_detail); getLoaderManager().initLoader(GGLOADER_ID, null, ggTeamLoaderCallbacks); final Toolbar toolbar = getActionBarToolbar(); toolbar.setNavigationIcon(R.drawable.ic_up); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); mHandler.post(new Runnable() { @Override public void run() { toolbar.setTitle(""); } }); mMaxHeaderElevation = getResources().getDimensionPixelSize(R.dimen.session_detail_max_header_elevation); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); mScrollView.addCallbacks(this); ViewTreeObserver vto = mScrollView.getViewTreeObserver(); if (vto.isAlive()) { vto.addOnGlobalLayoutListener(mGlobalLayoutListener); } mScrollViewChild = findViewById(R.id.scroll_view_child); mHeaderBox = (FrameLayout) findViewById(R.id.header_bar); mHeaderTeamName = (TextView) mHeaderBox.findViewById(R.id.team_name); mHeaderTeamLogo = (BezelImageView) mHeaderBox.findViewById(R.id.team_logo); mHeaderTeamLogo.setVisibility(View.INVISIBLE); mHeaderTeamName.getLayoutParams().height = UIUtils.calculateActionBarSize(this); mHeaderTeamName.setAlpha(0f); mDetailsContainer = (LinearLayout) mScrollViewChild.findViewById(R.id.card_container); recomputeScrollingConstants(); } @Override protected void onDestroy() { super.onDestroy(); if (mScrollView == null) { return; } ViewTreeObserver vto = mScrollView.getViewTreeObserver(); if (vto.isAlive()) { vto.removeOnGlobalLayoutListener(mGlobalLayoutListener); } } private void onFinishedGGLoad() { teamName = mTeam.name; LocalBroadcastManager.getInstance(mContext).sendBroadcast(new Intent(STATUS_LOAD_COMPLETE)); mHeaderTeamName.setText(mTeam.name); if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) { createCircularReveal(); } else { createCompatReveal(); } recomputeScrollingConstants(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void createCircularReveal() { mHeaderTeamLogo.setVisibility(View.VISIBLE); mHeaderTeamLogo.setImageBitmap(mTeam.logo); if (mHeaderBox.isAttachedToWindow()) { mHeaderTeamLogo.setTranslationY(-UIUtils.calculateActionBarSize(this) - mHeaderTeamLogo.getHeight()); mHeaderTeamLogo.animate().translationY(0).setDuration(100) .setInterpolator(new AccelerateDecelerateInterpolator()) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { int cx = (mHeaderBox.getLeft() + mHeaderBox.getRight()) / 2; int cy = (mHeaderBox.getTop() + mHeaderBox.getBottom()) / 2; int finalRadius = Math.max(mHeaderBox.getWidth(), mHeaderBox.getHeight()); final Animator anim = ViewAnimationUtils.createCircularReveal(mHeaderBox, cx, cy, 0, finalRadius); anim.setDuration(250); anim.setInterpolator(new AccelerateDecelerateInterpolator()); anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { mHeaderTeamName.setAlpha(1); mHeaderTeamLogo.setImageBitmap(mTeam.logo); mHeaderBox.setBackgroundColor(mTeam.palette .getDarkVibrantColor(getResources().getColor(R.color.theme_primary))); } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); anim.start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }).start(); } else { mHeaderTeamName.setAlpha(1); mHeaderTeamLogo.setImageBitmap(mTeam.logo); mHeaderBox.setBackgroundColor( mTeam.palette.getDarkVibrantColor(getResources().getColor(R.color.theme_primary))); } } private void createCompatReveal() { mHeaderTeamLogo.setVisibility(View.VISIBLE); mHeaderTeamLogo.setImageBitmap(mTeam.logo); mHeaderTeamLogo.setTranslationY(-UIUtils.calculateActionBarSize(this) - mHeaderTeamLogo.getHeight()); mHeaderTeamLogo.animate().translationY(0).setDuration(100) .setInterpolator(new AccelerateDecelerateInterpolator()) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { mHeaderTeamName.animate().alpha(1).setDuration(150) .setInterpolator(new AccelerateDecelerateInterpolator()).start(); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), getResources().getColor(R.color.theme_primary), mTeam.palette.getDarkVibrantColor(getResources().getColor(R.color.theme_primary))); colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { mHeaderBox.setBackgroundColor((Integer) animator.getAnimatedValue()); } }); colorAnimation.setDuration(150); colorAnimation.start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }).start(); } public Team getTeam() { return mTeam; } public void recomputeScrollingConstants() { mHeaderHeightPixels = mHeaderBox.getHeight(); mHeaderTeamName.setTranslationX(0); mHeaderTextXTranslation = mHeaderTeamName.getX() - UIUtils.dpToPx(this.getResources().getDisplayMetrics(), 56); mHeaderOffset = mHeaderHeightPixels - UIUtils.calculateActionBarSize(this); ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) mDetailsContainer.getLayoutParams(); if (mlp.topMargin != mHeaderHeightPixels) { mlp.topMargin = mHeaderHeightPixels; mDetailsContainer.setLayoutParams(mlp); } onScrollChanged(0, 0); } @Override public void onScrollChanged(int deltaX, int deltaY) { float scrollY = mScrollView.getScrollY(); float newTop = Math.max(0, scrollY - mHeaderOffset); mHeaderBox.setTranslationY(newTop); float gapFillProgress = Math .min(Math.max(UIUtils.getProgress(Math.round(scrollY), 0, Math.round(mHeaderOffset)), 0), 1); mHeaderTeamLogo.setAlpha((float) Math.max(0, 1 - (gapFillProgress * 1.25))); mHeaderTeamName.setTranslationX(gapFillProgress * -mHeaderTextXTranslation); ViewCompat.setElevation(mHeaderBox, gapFillProgress * mMaxHeaderElevation); } /* private LoaderManager.LoaderCallbacks<Cursor> teamLoaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri resultsUri; String sortOrder; String selection; switch (id) { case ULOADER_ID: sortOrder = MatchContract.SeriesEntry.COLUMN_DATETIME + " ASC"; resultsUri = MatchContract.SeriesEntry .buildSeriesUriWithAfterTime(TimeUtils.getUTCTime()); selection = MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry.COLUMN_TEAM_ONE_NAME + " = ? " + " OR " + MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry.COLUMN_TEAM_TWO_NAME + " = ? "; return new CursorLoader( mContext, resultsUri, UPCOMING_PROJECTION, selection, new String[] {teamName, teamName}, sortOrder ); case RLOADER_ID: sortOrder = MatchContract.SeriesEntry.COLUMN_DATETIME + " DESC"; resultsUri = MatchContract.ResultEntry.CONTENT_URI; selection = MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry.COLUMN_TEAM_ONE_NAME + " = ? " + " OR " + MatchContract.SeriesEntry.TABLE_NAME + "." + MatchContract.SeriesEntry.COLUMN_TEAM_TWO_NAME + " = ? "; return new CursorLoader( mContext, resultsUri, RESULT_PROJECTION, selection, new String[] {teamName, teamName}, sortOrder ); } return null; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { switch (loader.getId()) { case ULOADER_ID: case RLOADER_ID: } } @Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case ULOADER_ID: case RLOADER_ID: } } };*/ private LoaderManager.LoaderCallbacks<Team> ggTeamLoaderCallbacks = new LoaderManager.LoaderCallbacks<Team>() { @Override public Loader<Team> onCreateLoader(int id, Bundle args) { return new TeamDetailLoader(getApplicationContext(), "http://www.gosugamers.net/dota2/teams/2592-evil-geniuses-dota2"); } @Override public void onLoadFinished(Loader<Team> loader, Team data) { mTeam = data; onFinishedGGLoad(); } @Override public void onLoaderReset(Loader<Team> loader) { } }; }