package com.bigpupdev.synodroid.utils; import com.slidingmenu.lib.SlidingMenu; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; /** * An small bar indicating the title of the previous, * current and next page to be shown in a ViewPager. * Made to resemble the indicator in the Google+ application * in function. * * @author Mark Gj�l @ Zylinc */ public class ViewPagerIndicator extends RelativeLayout implements OnPageChangeListener { private static final int PADDING = 5; SlidingMenu menu = null; TextView mPrevious; TextView mCurrent; TextView mNext; int mCurItem; LinearLayout mPreviousGroup; LinearLayout mNextGroup; int mArrowPadding; int mSize; ImageView mCurrentIndicator; ImageView mPrevArrow; ImageView mNextArrow; int[] mFocusedTextColor; int[] mUnfocusedTextColor; OnClickListener mOnClickHandler; public interface PageInfoProvider{ String getTitle(int pos); } public interface OnClickListener{ void onNextClicked(View v); void onPreviousClicked(View v); void onCurrentClicked(View v); } public void setOnClickListener(OnClickListener handler){ this.mOnClickHandler = handler; mPreviousGroup.setOnClickListener(new OnPreviousClickedListener()); mCurrent.setOnClickListener(new OnCurrentClickedListener()); mNextGroup.setOnClickListener(new OnNextClickedListener()); } public int getCurrentPosition(){ return mCurItem; } PageInfoProvider mPageInfoProvider; public void setPageInfoProvider(PageInfoProvider pageInfoProvider){ this.mPageInfoProvider = pageInfoProvider; } public void setFocusedTextColor(int[] col){ System.arraycopy(col, 0, mFocusedTextColor, 0, 3); updateColor(0); } public void setUnfocusedTextColor(int[] col){ System.arraycopy(col, 0, mUnfocusedTextColor, 0, 3); mNext.setTextColor(Color.argb(255, col[0], col[1], col[2])); mPrevious.setTextColor(Color.argb(255, col[0], col[1], col[2])); updateColor(0); } /** * Initialization * * @param startPos The initially selected element in the ViewPager * @param size Total amount of elements in the ViewPager * @param pageInfoProvider Interface that returns page titles */ public void init(int startPos, int size, PageInfoProvider pageInfoProvider){ setPageInfoProvider(pageInfoProvider); this.mSize = size; setText(startPos - 1); mCurItem = startPos; } public ViewPagerIndicator(Context context, AttributeSet attrs) { super(context, attrs); addContent(); } public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyle){ super(context, attrs, defStyle); addContent(); } public ViewPagerIndicator(Context context) { super(context); addContent(); } /** * Add drawables for arrows * * @param prev Left pointing arrow * @param next Right pointing arrow */ public void setArrows(Drawable prev, Drawable next){ this.mPrevArrow = new ImageView(getContext()); this.mPrevArrow.setImageDrawable(prev); this.mNextArrow = new ImageView(getContext()); this.mNextArrow.setImageDrawable(next); LinearLayout.LayoutParams arrowLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); arrowLayoutParams.gravity = Gravity.CENTER; mPreviousGroup.removeAllViews(); mPreviousGroup.addView(mPrevArrow, arrowLayoutParams); mPreviousGroup.addView(mPrevious, arrowLayoutParams); mPrevious.setPadding(PADDING, 0, 0, 0); mNext.setPadding(0, 0, PADDING, 0); mArrowPadding = PADDING + prev.getIntrinsicWidth(); mNextGroup.addView(mNextArrow, arrowLayoutParams); updateArrows(mCurItem); } /** * Create all views, build the layout */ private void addContent(){ mFocusedTextColor = new int[]{0, 0, 0}; mUnfocusedTextColor = new int[]{190, 190, 190}; // Text views mPrevious = new TextView(getContext()); mCurrent = new TextView(getContext()); mNext = new TextView(getContext()); RelativeLayout.LayoutParams previousParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); previousParams.addRule(RelativeLayout.ALIGN_LEFT); RelativeLayout.LayoutParams currentParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); currentParams.addRule(RelativeLayout.CENTER_HORIZONTAL); RelativeLayout.LayoutParams nextParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); nextParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); // Groups holding text and arrows mPreviousGroup = new LinearLayout(getContext()); mPreviousGroup.setOrientation(LinearLayout.HORIZONTAL); mNextGroup = new LinearLayout(getContext()); mNextGroup.setOrientation(LinearLayout.HORIZONTAL); mPreviousGroup.addView(mPrevious, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mNextGroup.addView(mNext, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); addView(mPreviousGroup, previousParams); addView(mCurrent, currentParams); addView(mNextGroup, nextParams); mPrevious.setSingleLine(); mCurrent.setSingleLine(); mNext.setSingleLine(); mPrevious.setText("previous"); mCurrent.setText("current"); mNext.setText("next"); mPrevious.setClickable(false); mNext.setClickable(false); mCurrent.setClickable(true); mPreviousGroup.setClickable(true); mNextGroup.setClickable(true); // Set colors mNext.setTextColor(Color.argb(255, mUnfocusedTextColor[0], mUnfocusedTextColor[1], mUnfocusedTextColor[2])); mPrevious.setTextColor(Color.argb(255, mUnfocusedTextColor[0], mUnfocusedTextColor[1], mUnfocusedTextColor[2])); updateColor(0); } public void setSlidingMenu(SlidingMenu p_menu){ menu = p_menu; } public void onPageScrollStateChanged(int state) { } public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { positionOffsetPixels = adjustOffset(positionOffsetPixels); position = updatePosition(position, positionOffsetPixels); setText(position - 1); updateColor(positionOffsetPixels); updateArrows(position); updatePositions(positionOffsetPixels); if (menu != null){ switch (position) { case 0: menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); break; default: menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN); break; } } } void updatePositions(int positionOffsetPixels){ int textWidth = mCurrent.getWidth() - mCurrent.getPaddingLeft() - mCurrent.getPaddingRight(); int maxOffset = this.getWidth() / 2 - textWidth / 2 - mArrowPadding; if(positionOffsetPixels > 0){ maxOffset -= this.getPaddingLeft(); int offset = Math.min(positionOffsetPixels, maxOffset - 1); mCurrent.setPadding(0, 0, 2 * offset, 0); }else{ maxOffset -= this.getPaddingRight(); int offset = Math.max(positionOffsetPixels, -maxOffset); mCurrent.setPadding(-2 * offset, 0, 0, 0); } } /** * Hide arrows if we can't scroll further * * @param position */ void updateArrows(int position){ if(mPrevArrow != null){ mPrevArrow.setVisibility(position == 0 ? View.INVISIBLE : View.VISIBLE); mNextArrow.setVisibility(position == mSize - 1 ? View.INVISIBLE : View.VISIBLE); } } /** * Adjust position to be the view that is showing the most. * * @param givenPosition * @param offset * @return */ int updatePosition(int givenPosition, int offset){ int pos; if(offset < 0){ pos = givenPosition + 1; }else{ pos = givenPosition; } return pos; } /** * Fade "currently showing" color depending on it's position * * @param offset */ void updateColor(int offset){ offset = Math.abs(offset); // Initial condition: offset is always 0, this.getWidth is also 0! 0/0 = NaN int width = this.getWidth(); float fraction = width == 0 ? 0 : offset / ((float)width / 4.0f); fraction = Math.min(1, fraction); int r = (int)(mUnfocusedTextColor[0] * fraction + mFocusedTextColor[0] * (1 - fraction)); int g = (int)(mUnfocusedTextColor[1] * fraction + mFocusedTextColor[1] * (1 - fraction)); int b = (int)(mUnfocusedTextColor[2] * fraction + mFocusedTextColor[2] * (1 - fraction)); mCurrent.setTextColor(Color.argb(255, r, g, b)); } /** * Update text depending on it's position * * @param prevPos */ void setText(int prevPos){ if(prevPos < 0){ mPrevious.setText(""); }else{ mPrevious.setText(mPageInfoProvider.getTitle(prevPos)); } mCurrent.setText(mPageInfoProvider.getTitle(prevPos + 1)); if(prevPos + 2 == this.mSize){ mNext.setText(""); }else{ mNext.setText(mPageInfoProvider.getTitle(prevPos + 2)); } } // Original: // 244, 245, 0, 1, 2 // New: // -2, -1, 0, 1, 2 int adjustOffset(int positionOffsetPixels){ // Move offset half width positionOffsetPixels += this.getWidth() / 2; // Clamp to width positionOffsetPixels %= this.getWidth(); // Center around zero positionOffsetPixels -= this.getWidth() / 2; return positionOffsetPixels; } public void onPageSelected(int position) { // Reset padding when the page is finally selected (May not be necessary) mCurrent.setPadding(0, 0, 0, 0); mCurItem = position; } class OnPreviousClickedListener implements android.view.View.OnClickListener{ public void onClick(View v) { if(mOnClickHandler != null){ mOnClickHandler.onPreviousClicked(ViewPagerIndicator.this); } } } class OnCurrentClickedListener implements android.view.View.OnClickListener{ public void onClick(View v) { if(mOnClickHandler != null){ mOnClickHandler.onCurrentClicked(ViewPagerIndicator.this); } } } class OnNextClickedListener implements android.view.View.OnClickListener{ public void onClick(View v) { if(mOnClickHandler != null){ mOnClickHandler.onNextClicked(ViewPagerIndicator.this); } } } }