/*
* Copyright 2013 Chris Banes
*
* 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 uk.co.senab.actionbarpulltorefresh.library;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* Default Header Transformer.
*/
public class DefaultHeaderTransformer extends PullToRefreshAttacher.HeaderTransformer {
private ViewGroup mContentLayout;
private TextView mHeaderTextView;
private ProgressBar mHeaderProgressBar;
private CharSequence mPullRefreshLabel, mRefreshingLabel, mReleaseLabel;
private boolean mUseCustomProgressColor = false;
private int mProgressDrawableColor;
private final Interpolator mInterpolator = new AccelerateInterpolator();
protected DefaultHeaderTransformer() {
final int min = getMinimumApiLevel();
if (Build.VERSION.SDK_INT < min) {
throw new IllegalStateException("This HeaderTransformer is designed to run on SDK "
+ min
+ "+. If using ActionBarSherlock or ActionBarCompat you should use the appropriate provided extra.");
}
}
@Override
public void onViewCreated(Activity activity, View headerView) {
// Get ProgressBar and TextView. Also set initial text on TextView
mHeaderProgressBar = (ProgressBar) headerView.findViewById(R.id.ptr_progress);
mHeaderTextView = (TextView) headerView.findViewById(R.id.ptr_text);
// Apply any custom ProgressBar colors
applyProgressBarColor();
// Labels to display
mPullRefreshLabel = activity.getString(R.string.pull_to_refresh_pull_label);
mRefreshingLabel = activity.getString(R.string.pull_to_refresh_refreshing_label);
mReleaseLabel = activity.getString(R.string.pull_to_refresh_release_label);
// Retrieve the Action Bar size from the Activity's theme
mContentLayout = (ViewGroup) headerView.findViewById(R.id.ptr_content);
if (mContentLayout != null) {
mContentLayout.getLayoutParams().height = getActionBarSize(activity);
mContentLayout.requestLayout();
}
// Retrieve the Action Bar background from the Activity's theme (see #93).
Drawable abBg = getActionBarBackground(activity);
if (abBg != null) {
// If we do not have a opaque background we just display a solid solid behind it
if (abBg.getOpacity() != PixelFormat.OPAQUE) {
View view = headerView.findViewById(R.id.ptr_text_opaque_bg);
if (view != null) {
view.setVisibility(View.VISIBLE);
}
}
mHeaderTextView.setBackgroundDrawable(abBg);
}
// Retrieve the Action Bar Title Style from the Action Bar's theme
Context abContext = headerView.getContext();
final int titleTextStyle = getActionBarTitleStyle(abContext);
if (titleTextStyle != 0) {
mHeaderTextView.setTextAppearance(abContext, titleTextStyle);
}
// Call onReset to make sure that the View is consistent
onReset();
}
@Override
public void onReset() {
// Reset Progress Bar
if (mHeaderProgressBar != null) {
mHeaderProgressBar.setVisibility(View.GONE);
mHeaderProgressBar.setProgress(0);
mHeaderProgressBar.setIndeterminate(false);
}
// Reset Text View
if (mHeaderTextView != null) {
mHeaderTextView.setVisibility(View.VISIBLE);
mHeaderTextView.setText(mPullRefreshLabel);
}
// Reset the Content Layout
if (mContentLayout != null) {
mContentLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void onPulled(float percentagePulled) {
if (mHeaderProgressBar != null) {
mHeaderProgressBar.setVisibility(View.VISIBLE);
final float progress = mInterpolator.getInterpolation(percentagePulled);
mHeaderProgressBar.setProgress(Math.round(mHeaderProgressBar.getMax() * progress));
}
}
@Override
public void onRefreshStarted() {
if (mHeaderTextView != null) {
mHeaderTextView.setText(mRefreshingLabel);
}
if (mHeaderProgressBar != null) {
mHeaderProgressBar.setVisibility(View.VISIBLE);
mHeaderProgressBar.setIndeterminate(true);
}
}
@Override
public void onReleaseToRefresh() {
if (mHeaderTextView != null) {
mHeaderTextView.setText(mReleaseLabel);
}
if (mHeaderProgressBar != null) {
mHeaderProgressBar.setProgress(mHeaderProgressBar.getMax());
}
}
@Override
public void onRefreshMinimized() {
// Here we fade out most of the header, leaving just the progress bar
if (mContentLayout != null) {
mContentLayout.startAnimation(AnimationUtils
.loadAnimation(mContentLayout.getContext(), R.anim.fade_out));
mContentLayout.setVisibility(View.INVISIBLE);
}
}
/**
* Set color to apply to the progress bar. Automatically enables usage of the custom color. Use
* {@link #setProgressBarColorEnabled(boolean)} to disable and re-enable the custom color usage.
* <p/>
* The best way to apply a color is to load the color from resources: {@code
* setProgressBarColor(getResources().getColor(R.color.your_color_name))}.
*
* @param color The color to use.
*/
public void setProgressBarColor(int color) {
mProgressDrawableColor = color;
setProgressBarColorEnabled(true);
}
/**
* Enable or disable the use of a custom progress bar color. You can set what color to use with
* {@link #setProgressBarColor(int)}, which also automatically enables custom color usage.
*/
public void setProgressBarColorEnabled(boolean enabled) {
mUseCustomProgressColor = enabled;
applyProgressBarColor();
}
/**
* Set Text to show to prompt the user is pull (or keep pulling).
*
* @param pullText - Text to display.
*/
public void setPullText(CharSequence pullText) {
mPullRefreshLabel = pullText;
if (mHeaderTextView != null) {
mHeaderTextView.setText(mPullRefreshLabel);
}
}
/**
* Set Text to show to tell the user that a refresh is currently in progress.
*
* @param refreshingText - Text to display.
*/
public void setRefreshingText(CharSequence refreshingText) {
mRefreshingLabel = refreshingText;
}
/**
* Set Text to show to tell the user has scrolled enough to refresh.
*
* @param releaseText - Text to display.
*/
public void setReleaseText(CharSequence releaseText) {
mReleaseLabel = releaseText;
}
private void applyProgressBarColor() {
if (mHeaderProgressBar != null) {
if (mUseCustomProgressColor) {
mHeaderProgressBar.getProgressDrawable()
.setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP);
mHeaderProgressBar.getIndeterminateDrawable()
.setColorFilter(mProgressDrawableColor, PorterDuff.Mode.SRC_ATOP);
} else {
mHeaderProgressBar.getProgressDrawable().clearColorFilter();
mHeaderProgressBar.getIndeterminateDrawable().clearColorFilter();
}
}
}
protected Drawable getActionBarBackground(Context context) {
int[] android_styleable_ActionBar = {android.R.attr.background};
// Need to get resource id of style pointed to from actionBarStyle
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarStyle, outValue, true);
// Now get action bar style values...
TypedArray abStyle = context.getTheme().obtainStyledAttributes(outValue.resourceId,
android_styleable_ActionBar);
try {
// background is the first attr in the array above so it's index is 0.
return abStyle.getDrawable(0);
} finally {
abStyle.recycle();
}
}
protected int getActionBarSize(Context context) {
int[] attrs = {android.R.attr.actionBarSize};
TypedArray values = context.getTheme().obtainStyledAttributes(attrs);
try {
return values.getDimensionPixelSize(0, 0);
} finally {
values.recycle();
}
}
protected int getActionBarTitleStyle(Context context) {
int[] android_styleable_ActionBar = {android.R.attr.titleTextStyle};
// Need to get resource id of style pointed to from actionBarStyle
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.actionBarStyle, outValue, true);
// Now get action bar style values...
TypedArray abStyle = context.getTheme().obtainStyledAttributes(outValue.resourceId,
android_styleable_ActionBar);
try {
// titleTextStyle is the first attr in the array above so it's index is 0.
return abStyle.getResourceId(0, 0);
} finally {
abStyle.recycle();
}
}
protected int getMinimumApiLevel() {
return Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}
}