package com.abewy.android.apps.klyph.app;
import java.util.List;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.v13.app.FragmentPagerAdapter;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.abewy.android.apps.klyph.KlyphApplication;
import com.abewy.android.apps.klyph.KlyphPreferences;
import com.abewy.android.apps.klyph.R;
import com.abewy.android.apps.klyph.core.KlyphDevice;
import com.abewy.android.apps.klyph.core.graph.GraphObject;
import com.abewy.android.apps.klyph.core.imageloader.ImageLoader;
import com.abewy.android.apps.klyph.core.request.BaseAsyncRequest;
import com.abewy.android.apps.klyph.core.request.RequestError;
import com.abewy.android.apps.klyph.core.request.Response;
import com.abewy.android.apps.klyph.fragment.IKlyphFragment;
import com.abewy.android.apps.klyph.request.AsyncRequest;
import com.abewy.android.apps.klyph.util.KlyphUtil;
import com.abewy.net.ConnectionState;
import com.viewpagerindicator.PageIndicator;
import com.viewpagerindicator.TabPageIndicator;
import com.viewpagerindicator.TitlePageIndicator;
public abstract class ProfileActivity extends TitledViewPagerActivity implements OnScrollListener
{
// Newsstand effect
private View mHeader;
private ImageView mHeaderPicture;
private ImageView mHeaderLogo;
private View headerNameButton;
private PageIndicator pageIndicator;
private int mMinHeaderTranslation;
private int mMinHeaderNameButtonTranslation;
private int mMinPageIndicatorTranslation;
private int mActionBarTitleColor;
private AlphaForegroundColorSpan mAlphaForegroundColorSpan;
private SpannableString mSpannableString;
private RectF mRect1 = new RectF();
private RectF mRect2 = new RectF();
private DecelerateInterpolator mSmoothInterpolator;
private float interpolation;
private int fakeHeaderHeight;
private int mActionBarHeight;
private int listPadding;
private View errorView;
private TextView errorTextView;
private Button errorButton;
private boolean isLoading;
private boolean isDestroyed = false;
private String id;
@Override
public void onCreate(final Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
final float ratio = getRatio();
final int coverImageHeaderHeight = (int) (KlyphDevice.getDeviceWidth() * ratio);
super.onCreate(savedInstanceState);
getActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.ab_background_transparent_gradient));
// Let the Application class know that the first launch is complete
// If we come from a notification, then do not show the ads
// When going back to main activity
KlyphApplication.getInstance().launchComplete();
id = getIntent().getStringExtra(getBundleIdParameter());
String name = getIntent().getStringExtra(getBundleNameParameter());
TitlePageIndicator titleIndicator = (TitlePageIndicator) findViewById(R.id.title_indicator);
TabPageIndicator tabIndicator = (TabPageIndicator) findViewById(R.id.tab_indicator);
if (KlyphPreferences.showTabPageIndicator())
titleIndicator.setVisibility(View.GONE);
else
tabIndicator.setVisibility(View.GONE);
mHeader = findViewById(R.id.header);
mHeaderPicture = (ImageView) findViewById(R.id.header_picture);
mHeaderLogo = (ImageView) findViewById(R.id.header_logo);
headerNameButton = findViewById(R.id.header_name_button);
pageIndicator = getPageIndicator();
errorView = findViewById(R.id.error_layout);
errorTextView = (TextView) findViewById(R.id.error_text);
errorButton = (Button) findViewById(R.id.retry_button);
ImageLoader.display((ImageView) mHeaderPicture, ImageLoader.FAKE_URI, true, R.drawable.cover_place_holder);
if (mHeaderLogo != null)
ImageLoader.display((ImageView) mHeaderLogo, ImageLoader.FAKE_URI, true, KlyphUtil.getProfilePlaceHolder(this));
initComponents();
mSmoothInterpolator = new DecelerateInterpolator();
mMinHeaderTranslation = -coverImageHeaderHeight + getActionBarHeight();
mActionBarTitleColor = 0xFFFFFF;
mSpannableString = new SpannableString(name);
mAlphaForegroundColorSpan = new AlphaForegroundColorSpan(mActionBarTitleColor);
setupActionBar();
final View content = findViewById(android.R.id.content);
if (hasCachedData(savedInstanceState))
{
content.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout()
{
content.getViewTreeObserver().removeGlobalOnLayoutListener(this);
loadCachedData(savedInstanceState);
}
});
}
else
{
loadData();
}
}
private void loadCachedData(Bundle savedInstanceState)
{
List<GraphObject> data = getCachedDataFromInstanceState(savedInstanceState);
onRequestSuccess(data);
onScroll(null, 0, 0, 0);
getPageIndicator().setCurrentItem(savedInstanceState.getInt("position"));
}
private void loadData()
{
isLoading = true;
invalidateOptionsMenu();
new AsyncRequest(getQuery(), id, getQueryParam(), new BaseAsyncRequest.Callback() {
@Override
public void onComplete(final Response response)
{
isLoading = false;
if (isDestroyed)
return;
runOnUiThread(new Runnable() {
@Override
public void run()
{
if (response.getError() == null)
{
onRequestSuccess(response.getGraphObjectList());
}
else
{
onRequestError(response.getError());
}
invalidateOptionsMenu();
}
});
}
}).execute();
}
@Override
protected int getCustomTheme()
{
return KlyphPreferences.getProfileTheme();
}
private void onRequestSuccess(List<GraphObject> result)
{
computeAndSetComponentsHeights();
if (result.size() > 0)
initComponentsOnRequestSucces(result);
getActionBar().show();
mHeader.setVisibility(View.VISIBLE);
if (KlyphDevice.isPortraitMode())
headerNameButton.setVisibility(View.VISIBLE);
showPageIndicator();
showViewPager();
if (KlyphPreferences.areBannerAdsEnabled())
initAds();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
if (isLoading)
{
MenuItem refreshItem = menu.add(Menu.NONE, R.id.menu_refresh, 1, R.string.refresh);
refreshItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
refreshItem.setActionView(R.layout.actionbar_item_refresh);
}
return super.onCreateOptionsMenu(menu);
}
private void onRequestError(RequestError error)
{
int errorText = R.string.request_error;
if (!ConnectionState.getInstance(this).isOnline())
{
errorText = R.string.request_connexion_error;
}
errorTextView.setText(errorText);
errorButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v)
{
errorView.setVisibility(View.GONE);
loadData();
}
});
errorView.setVisibility(View.VISIBLE);
}
@Override
protected int getInitialPosition()
{
return -1;
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
saveCachedDataToInstanceState(outState);
outState.putInt("position", getViewPager().getCurrentItem());
super.onSaveInstanceState(outState);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
int scrollY = getScrollY();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
{
scrollY += fakeHeaderHeight;
}
// sticky actionbar
mHeader.setTranslationY(Math.max(-scrollY, mMinHeaderTranslation));
headerNameButton.setTranslationY(Math.max(-scrollY, mMinHeaderNameButtonTranslation));
float ratio = clamp(headerNameButton.getTranslationY() / mMinHeaderNameButtonTranslation, 0.0f, 1.0f);
setTitleAlpha(clamp(5.0F * ratio - 4.0F, 0.0F, 1.0F));
if (KlyphDevice.isPortraitMode())
{
((View) getPageIndicator()).setTranslationY(Math.max(-scrollY, mMinPageIndicatorTranslation));
ratio = clamp(((View) getPageIndicator()).getTranslationY() / mMinPageIndicatorTranslation, 0.0f, 1.0f);
setPageIndicatorAlpha(clamp(5.0F * ratio - 4.0F, 0.0F, 1.0F));
}
else
{
setPageIndicatorAlpha(1.0f);
}
float tint = clamp(mHeader.getTranslationY() / mMinHeaderTranslation, 0.0f, 1.0f);
setHeaderImageTint(tint);
// move & scale
if (mHeaderLogo != null)
{
interpolation = mSmoothInterpolator.getInterpolation(ratio);
View actionBarIconView = getActionBarIconView();
getOnScreenRect(mRect1, mHeaderLogo);
getOnScreenRect(mRect2, actionBarIconView);
float scaleX = 1.0F + interpolation * (mRect2.width() / mRect1.width() - 1.0F);
float scaleY = 1.0F + interpolation * (mRect2.height() / mRect1.height() - 1.0F);
float translationX = 0.5F * (interpolation * (mRect2.left + mRect2.right - mRect1.left - mRect1.right));
float translationY = 0.5F * (interpolation * (mRect2.top + mRect2.bottom - mRect1.top - mRect1.bottom));
mHeaderLogo.setTranslationX(translationX);
mHeaderLogo.setTranslationY(translationY - mHeader.getTranslationY());
mHeaderLogo.setScaleX(scaleX);
mHeaderLogo.setScaleY(scaleY);
}
}
public int getScrollY()
{
IKlyphFragment f = (IKlyphFragment) ((FragmentPagerAdapter) getPagerAdapter()).getItem(getViewPager().getCurrentItem());
if (f == null || f.getListView() == null)
return 0;
listPadding = f.getListView().getPaddingTop();
View c = f.getListView().getChildAt(0);
if (c == null)
{
return 0;
}
int firstVisiblePosition = f.getListView().getFirstVisiblePosition();
int top = c.getTop();
int headerHeight = 0;
if (firstVisiblePosition >= 1)
{
headerHeight = fakeHeaderHeight;
}
// Log.d("UserActivity", "getScrollY: " + top + " " + headerHeight);
return -top + firstVisiblePosition * c.getHeight() + headerHeight + listPadding;
}
public static float clamp(float value, float max, float min)
{
return Math.max(Math.min(value, min), max);
}
private RectF getOnScreenRect(RectF rect, View view)
{
rect.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
return rect;
}
private ImageView getActionBarIconView()
{
return (ImageView) findViewById(android.R.id.home);
}
private void setupActionBar()
{
getActionBar().setIcon(R.drawable.ic_transparent);
getActionBar().setLogo(R.drawable.ic_transparent);
getActionBar().setTitle("");
}
private void setTitleAlpha(float alpha)
{
mAlphaForegroundColorSpan.setAlpha(alpha);
mSpannableString.setSpan(mAlphaForegroundColorSpan, 0, mSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
getActionBar().setTitle(mSpannableString);
}
private void setHeaderImageTint(float tint)
{
Log.d("ProfileActivity", "setHeaderImageTint: " + tint);
mHeaderPicture.setColorFilter(Color.argb((int) (tint * 0x66), 0, 0, 0), Mode.SRC_ATOP);
}
private void setPageIndicatorAlpha(float alpha)
{
float a = alpha * 255;
((View) getPageIndicator()).getBackground().setAlpha(255 - (int) a);
}
public int getActionBarHeight()
{
if (mActionBarHeight != 0)
{
return mActionBarHeight;
}
TypedValue mTypedValue = new TypedValue();
getTheme().resolveAttribute(android.R.attr.actionBarSize, mTypedValue, true);
mActionBarHeight = TypedValue.complexToDimensionPixelSize(mTypedValue.data, getResources().getDisplayMetrics());
return mActionBarHeight;
}
public static class AlphaForegroundColorSpan extends ForegroundColorSpan
{
private float mAlpha;
public AlphaForegroundColorSpan(int color)
{
super(color);
}
@Override
public void updateDrawState(TextPaint ds)
{
ds.setColor(getAlphaColor());
}
public void setAlpha(float alpha)
{
mAlpha = alpha;
}
public float getAlpha()
{
return mAlpha;
}
private int getAlphaColor()
{
int foregroundColor = getForegroundColor();
return Color.argb((int) (mAlpha * 255), Color.red(foregroundColor), Color.green(foregroundColor), Color.blue(foregroundColor));
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
}
protected void computeAndSetComponentsHeights()
{
final float ratio = getRatio();
int headerHeight = (int) (KlyphDevice.getDeviceWidth() * ratio);
final int headerNameButtonHeight = headerNameButton.getHeight();
final int pageIndicatorHeight = ((View) pageIndicator).getHeight();
final int actionBarHeight = getActionBarHeight();
fakeHeaderHeight = headerHeight + headerNameButtonHeight + pageIndicatorHeight;
mMinHeaderTranslation = -headerHeight + actionBarHeight + pageIndicatorHeight;
mMinHeaderNameButtonTranslation = -(headerHeight + headerNameButtonHeight) + actionBarHeight;
mMinPageIndicatorTranslation = -fakeHeaderHeight + actionBarHeight + pageIndicatorHeight;
/*Log.d("UserActivity", "computeAndSetComponentsHeights: headerHeight" + headerHeight);
// Log.d("UserActivity", "computeAndSetComponentsHeights: headerLogoHeight" + headerLogoHeight);
Log.d("UserActivity", "computeAndSetComponentsHeights: headerNameButtonHeight" + headerNameButtonHeight);
Log.d("UserActivity", "computeAndSetComponentsHeights: pageIndicatorHeight" + pageIndicatorHeight);
Log.d("UserActivity", "computeAndSetComponentsHeights: actionBarHeight" + actionBarHeight);
Log.d("UserActivity", "computeAndSetComponentsHeights: mMinHeaderTranslation" + mMinHeaderTranslation);
Log.d("UserActivity", "computeAndSetComponentsHeights: mMinHeaderNameButtonTranslation" + mMinHeaderNameButtonTranslation);
Log.d("UserActivity", "computeAndSetComponentsHeights: mMinPageIndicatorTranslation" + mMinPageIndicatorTranslation);
Log.d("UserActivity", "computeAndSetComponentsHeights: fakeHeaderHeight" + fakeHeaderHeight);
Log.d("UserActivity", "computeAndSetComponentsHeights: listGridHeaderHeight" + listGridHeaderHeight);*/
if (mHeaderLogo != null)
{
final int headerLogoHeight = mHeaderLogo.getHeight();
android.widget.FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) mHeaderLogo.getLayoutParams();
params.topMargin = (headerHeight) - (int) (headerLogoHeight / 2);
mHeaderLogo.setLayoutParams(params);
}
android.widget.FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) headerNameButton.getLayoutParams();
params.topMargin = headerHeight;
headerNameButton.setLayoutParams(params);
params = (android.widget.FrameLayout.LayoutParams) ((View) pageIndicator).getLayoutParams();
if (KlyphDevice.isPortraitMode())
{
params.topMargin = headerHeight + headerNameButtonHeight;
}
else
{
params.topMargin = actionBarHeight;
}
((View) pageIndicator).setLayoutParams(params);
}
// Methods to override
protected abstract float getRatio();
protected abstract int getQuery();
protected abstract String getQueryParam();
/**
* That's where you make some view = findViewById(R.id.something) stuff
*/
protected abstract void initComponents();
protected abstract String getBundleIdParameter();
protected abstract String getBundleNameParameter();
protected abstract boolean hasCachedData(Bundle savedInstanceState);
protected abstract List<GraphObject> getCachedDataFromInstanceState(Bundle savedInstanceState);
protected abstract void saveCachedDataToInstanceState(Bundle outState);
protected abstract void initComponentsOnRequestSucces(List<GraphObject> result);
protected String getElementId()
{
return id;
}
protected ImageView getHeaderPicture()
{
return mHeaderPicture;
}
protected ImageView getHeaderLogo()
{
return mHeaderLogo;
}
protected int getFakeHeaderHeight()
{
return fakeHeaderHeight;
}
@Override
public void onDestroy()
{
super.onDestroy();
mHeader = null;
mHeaderPicture = null;
mHeaderLogo = null;
headerNameButton = null;
pageIndicator = null;
mAlphaForegroundColorSpan = null;
mSpannableString = null;
mRect1 = null;
mRect2 = null;
mSmoothInterpolator = null;
errorView = null;
errorTextView = null;
errorButton = null;
isDestroyed = true;
}
}