48、ViewFlow ---- 滑动广告页
2015-08-07 15:42
459 查看
package org.taptwo.android.widget; import com.viewflowtest.cjy.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.os.AsyncTask; import android.util.AttributeSet; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Animation.AnimationListener; public class CircleFlowIndicator extends View implements FlowIndicator, AnimationListener { private static final int STYLE_STROKE = 0; private static final int STYLE_FILL = 1; private float radius = 4; private float circleSeparation = 2*radius+radius; private float activeRadius = 0.5f; private int fadeOutTime = 0; private final Paint mPaintInactive = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint mPaintActive = new Paint(Paint.ANTI_ALIAS_FLAG); private ViewFlow viewFlow; private int currentScroll = 0; private int flowWidth = 0; private FadeTimer timer; public AnimationListener animationListener = this; private Animation animation; private boolean mCentered = false; /** * Default constructor * * @param context */ public CircleFlowIndicator(Context context) { super(context); initColors(0xFFFFFFFF, 0xFFFFFFFF, STYLE_FILL, STYLE_STROKE); } /** * The contructor used with an inflater * * @param context * @param attrs */ public CircleFlowIndicator(Context context, AttributeSet attrs) { super(context, attrs); // Retrieve styles attributs TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleFlowIndicator); // Gets the inactive circle type, defaulting to "fill" int activeType = a.getInt(R.styleable.CircleFlowIndicator_activeType, STYLE_FILL); int activeDefaultColor = 0xFFFFFFFF; // Get a custom inactive color if there is one int activeColor = a .getColor(R.styleable.CircleFlowIndicator_activeColor, activeDefaultColor); // Gets the inactive circle type, defaulting to "stroke" int inactiveType = a.getInt( R.styleable.CircleFlowIndicator_inactiveType, STYLE_STROKE); int inactiveDefaultColor = 0x44FFFFFF; // Get a custom inactive color if there is one int inactiveColor = a.getColor( R.styleable.CircleFlowIndicator_inactiveColor, inactiveDefaultColor); // Retrieve the radius radius = a.getDimension(R.styleable.CircleFlowIndicator_radius, 4.0f); circleSeparation = a.getDimension(R.styleable.CircleFlowIndicator_circleSeparation, 2*radius+radius); activeRadius = a.getDimension(R.styleable.CircleFlowIndicator_activeRadius, 0.5f); // Retrieve the fade out time fadeOutTime = a.getInt(R.styleable.CircleFlowIndicator_fadeOut, 0); mCentered = a.getBoolean(R.styleable.CircleFlowIndicator_centered, false); initColors(activeColor, inactiveColor, activeType, inactiveType); } private void initColors(int activeColor, int inactiveColor, int activeType, int inactiveType) { // Select the paint type given the type attr switch (inactiveType) { case STYLE_FILL: mPaintInactive.setStyle(Style.FILL); break; default: mPaintInactive.setStyle(Style.STROKE); } mPaintInactive.setColor(inactiveColor); // Select the paint type given the type attr switch (activeType) { case STYLE_STROKE: mPaintActive.setStyle(Style.STROKE); break; default: mPaintActive.setStyle(Style.FILL); } mPaintActive.setColor(activeColor); } /* * (non-Javadoc) * * @see android.view.View#onDraw(android.graphics.Canvas) */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int count = 3; if (viewFlow != null) { count = viewFlow.getViewsCount(); } //this is the amount the first circle should be offset to make the entire thing centered float centeringOffset = 0; int leftPadding = getPaddingLeft(); // Draw stroked circles for (int iLoop = 0; iLoop < count; iLoop++) { canvas.drawCircle(leftPadding + radius + (iLoop * circleSeparation) + centeringOffset, getPaddingTop() + radius, radius, mPaintInactive); } float cx = 0; if (flowWidth != 0) { // Draw the filled circle according to the current scroll cx = (currentScroll * circleSeparation) / flowWidth; } // The flow width has been upadated yet. Draw the default position canvas.drawCircle(leftPadding + radius + cx+centeringOffset, getPaddingTop() + radius, radius + activeRadius, mPaintActive); } /* * (non-Javadoc) * * @see * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android * .view.View, int) */ @Override public void onSwitched(View view, int position) { } /* * (non-Javadoc) * * @see * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android * .widget.ViewFlow) */ @Override public void setViewFlow(ViewFlow view) { resetTimer(); viewFlow = view; flowWidth = viewFlow.getWidth(); invalidate(); } /* * (non-Javadoc) * * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int, * int) */ @Override public void onScrolled(int h, int v, int oldh, int oldv) { setVisibility(View.VISIBLE); resetTimer(); flowWidth = viewFlow.getWidth(); if(viewFlow.getViewsCount()*flowWidth!=0){ currentScroll = h%(viewFlow.getViewsCount()*flowWidth); }else { currentScroll = h; } invalidate(); } /* * (non-Javadoc) * * @see android.view.View#onMeasure(int, int) */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } /** * Determines the width of this view * * @param measureSpec * A measureSpec packed into an int * @return The width of the view, honoring constraints from measureSpec */ private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // We were told how big to be if (specMode == MeasureSpec.EXACTLY) { result = specSize; } // Calculate the width according the views count else { int count = 3; if (viewFlow != null) { count = viewFlow.getViewsCount(); } float temp = circleSeparation - 2*radius; result = (int) (getPaddingLeft() + getPaddingRight() + (count * 2 * radius) + (count - 1) * temp + 1); // Respect AT_MOST value if that was what is called for by // measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * Determines the height of this view * * @param measureSpec * A measureSpec packed into an int * @return The height of the view, honoring constraints from measureSpec */ private int measureHeight(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); // We were told how big to be if (specMode == MeasureSpec.EXACTLY) { result = specSize; } // Measure the height else { result = (int) (2 * radius + getPaddingTop() + getPaddingBottom() + 1); // Respect AT_MOST value if that was what is called for by // measureSpec if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * Sets the fill color * * @param color * ARGB value for the text */ public void setFillColor(int color) { mPaintActive.setColor(color); invalidate(); } /** * Sets the stroke color * * @param color * ARGB value for the text */ public void setStrokeColor(int color) { mPaintInactive.setColor(color); invalidate(); } /** * Resets the fade out timer to 0. Creating a new one if needed */ private void resetTimer() { // Only set the timer if we have a timeout of at least 1 millisecond if (fadeOutTime > 0) { // Check if we need to create a new timer if (timer == null || timer._run == false) { // Create and start a new timer timer = new FadeTimer(); timer.execute(); } else { // Reset the current tiemr to 0 timer.resetTimer(); } } } /** * Counts from 0 to the fade out time and animates the view away when * reached */ private class FadeTimer extends AsyncTask<Void, Void, Void> { // The current count private int timer = 0; // If we are inside the timing loop private boolean _run = true; public void resetTimer() { timer = 0; } @Override protected Void doInBackground(Void... arg0) { while (_run) { try { // Wait for a millisecond Thread.sleep(1); // Increment the timer timer++; // Check if we've reached the fade out time if (timer == fadeOutTime) { // Stop running _run = false; } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Void result) { animation = AnimationUtils.loadAnimation(getContext(), android.R.anim.fade_out); animation.setAnimationListener(animationListener); startAnimation(animation); } } @Override public void onAnimationEnd(Animation animation) { setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }
View Code
package org.taptwo.android.widget; import org.taptwo.android.widget.ViewFlow.ViewSwitchListener; /** * An interface which defines the contract between a ViewFlow and a * FlowIndicator.<br/> * A FlowIndicator is responsible to show an visual indicator on the total views * number and the current visible view.<br/> * */ public interface FlowIndicator extends ViewSwitchListener { /** * Set the current ViewFlow. This method is called by the ViewFlow when the * FlowIndicator is attached to it. * * @param view */ public void setViewFlow(ViewFlow view); /** * The scroll position has been changed. A FlowIndicator may implement this * method to reflect the current position * * @param h * @param v * @param oldh * @param oldv */ public void onScrolled(int h, int v, int oldh, int oldv); }
values/attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ViewFlow"> <attr name="sidebuffer" format="integer" /> </declare-styleable> <declare-styleable name="CircleFlowIndicator"> <attr name="activeColor" format="color" /> <attr name="inactiveColor" format="color" /> <attr name="radius" format="dimension" /> <attr name="centered" format="boolean" /> <attr name="fadeOut" format="integer" /> <attr name="inactiveType"> <flag name="stroke" value="0" /> <flag name="fill" value="1" /> </attr> <attr name="activeType"> <flag name="stroke" value="0" /> <flag name="fill" value="1" /> </attr> <attr name="circleSeparation" format="dimension" /> <attr name="activeRadius" format="dimension" /> </declare-styleable> </resources>
相关文章推荐
- Java构造和解析Json数据的两种方法
- 数据库表的查询操作实践演练(实验三)
- uva 12558 Egyptian Fractions (HARD version)
- prestoDB搭建小得
- JQuery中$.ajax()方法参数详解
- HTML5 中的 Web SQL Database 来构建应用程序
- 分享下多年积累JAVA程序员成长之路
- uva11082 Matrix Decompressing (最大流)
- ios网络请求 get——post 区别
- 彻底解决android中Textview控件文本自动换行问题
- 用IoAllocateIrp创建IRP
- poj 2406 Power Strings
- body的margin问题。
- hdu 5362 Just A String 2015多校联合训练赛#6 动态规划
- jQuery.extend 函数详解
- jQuery实现信息提示框(带有圆角框与动画)效果
- Mac版的Android Eclipse识别安卓真机
- ApkTool在Mac上的安装和使用
- SlickEdit 的安装与配置
- Object源码研究2——getClass()方法分析