Android新聞廣告條滾動效果
項目中需要用到類似公告欄的控件,能用的基本不支持多行顯示,于是只好自己動手,苦于沒有自定義過一個像樣的控件,借鑒Android公告條demo,實現(xiàn)了多行向上滾動的控件。在原控件基礎(chǔ)之上添加如下功能:
•傳入數(shù)據(jù)分頁顯示
•添加Left Drawable
•手指觸摸事件處理
•添加3D動畫翻滾效果
效果圖

源碼
package com.android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.Transformation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.sd2w.market.client.R;
import java.util.ArrayList;
import java.util.List;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
/**
* 公告滾動區(qū)
*
* @author 祁連山
* @version 1.0
* @date 2016-08-17
*/
public class RollingView extends FrameLayout implements OnClickListener {
// 默認動畫執(zhí)行時間
private static final int ANIMATION_DURATION = 1000;
// 延遲滾動時間間隔
private long mDuration = 3000;
// 字體顏色
private int mTextColor = 0xff000000;
// 點擊后字體顏色
private int mClickColor = 0xff0099ff;
// 字體大小
private float mTextSize = 14;
// 行間距
private int mTextPadding = 10;
// 畫筆
private Paint mPaint;
// 默認每頁信息數(shù)
private int mPageSize = 3;
// 最后一頁余數(shù)
private int mUpLimited = mPageSize;
// 當(dāng)前顯示頁碼
private int mCurrentPage = 0;
// 總分頁數(shù)
private int mPageCount;
// 左圖片
private int mLeftDrawable;
// 分頁數(shù)據(jù)對象
private List<LinearLayout> mRollingPages;
// 默認動畫
private AnimationSet mEnterAnimSet;
private AnimationSet mExitAnimSet;
private RollingRunnable mRunnable;
private Handler mHandler;
private onItemClickListener mClickListener;
// 布局參數(shù)
private LayoutParams mFrameParams;
private LinearLayout.LayoutParams mLinearParams;
//mEnterDownAnim,mOutUp分別構(gòu)成向下翻頁的進出動畫
private Rotate3dAnimation mEnterDownAnim;
private Rotate3dAnimation mExitUpAnim;
//mEnterUpAnim,mOutDown分別構(gòu)成向下翻頁的進出動畫
private Rotate3dAnimation mEnterUpAnim;
private Rotate3dAnimation mExitDownAnim;
public RollingView(Context context) {
this(context, null);
}
public RollingView(Context context, AttributeSet attrs) {
super(context, attrs);
// 從xml中獲取屬性
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.RollingView);
mTextSize = array.getDimension(R.styleable.RollingView_textSize, mTextSize);
mTextColor = array.getColor(R.styleable.RollingView_textColor, mTextColor);
array.recycle();
// 創(chuàng)建默認顯示隱藏動畫
createEnterAnimation();
createExitAnimation();
// 初始化畫筆
mPaint = new TextPaint();
// 初始化Handler對象
mHandler = new Handler(Looper.getMainLooper());
mEnterDownAnim = createAnim(-90, 0, true, true);
mExitUpAnim = createAnim(0, 90, false, true);
mEnterUpAnim = createAnim(90, 0, true, false);
mExitDownAnim = createAnim(0, -90, false, false);
}
private Rotate3dAnimation createAnim(float start, float end, boolean turnIn, boolean turnUp) {
final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, turnIn, turnUp);
rotation.setDuration(300);
rotation.setFillAfter(false);
rotation.setInterpolator(new AccelerateInterpolator());
return rotation;
}
/**
* 設(shè)置分頁大小
*
* @param pageSize
*/
public void setPageSize(int pageSize) {
this.mPageSize = this.mUpLimited = pageSize;
}
/**
* 設(shè)置延遲時間
*
* @param millionSeconds
*/
public void setDelayedDuration(long millionSeconds) {
this.mDuration = millionSeconds;
}
/**
* 設(shè)置顯示動畫
*
* @param animation
*/
public void setEnterAnimation(AnimationSet animation) {
mEnterAnimSet = animation;
}
/**
* 設(shè)置隱藏動畫
*
* @param animation
*/
public void setExitAnimation(AnimationSet animation) {
mExitAnimSet = animation;
}
/**
* 設(shè)置行距
*
* @param padding
*/
public void setTextPadding(int padding) {
this.mTextPadding = padding;
}
/**
* 設(shè)置點擊后字體顏色
*
* @param color
*/
public void setClickColor(int color) {
this.mClickColor = color;
}
/**
* 設(shè)置左圖片
*
* @param drawable
*/
public void setLeftDrawable(int drawable) {
this.mLeftDrawable = drawable;
}
/**
* 設(shè)置點擊事件
*
* @param clickListener
*/
public void setOnItemClickListener(onItemClickListener clickListener) {
if (null == clickListener) return;
this.mClickListener = clickListener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 如果是未指定大小,那么設(shè)置寬為300px
int exceptWidth = 300;
int exceptHeight = 0;
// 計算高度,如果將高度設(shè)置為textSize會很丑,因為文字有默認的上下邊距。
if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) {
if (mTextSize > 0) {
mPaint.setTextSize(mTextSize);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
exceptHeight = (int) (fontMetrics.bottom - fontMetrics.top);
}
}
int width = resolveSize(exceptWidth, widthMeasureSpec);
int height = resolveSize(exceptHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public void setRollingText(List<String> array) {
if (null == array || array.isEmpty()) return;
this.removeAllViews();
if (mRollingPages == null) {
mRollingPages = new ArrayList<>();
}
mRollingPages.clear();
// 計算商數(shù)
int quotient = array.size() / mPageSize;
// 計算余數(shù)
int remainder = array.size() % mPageSize;
// 計算需要創(chuàng)建多少頁
mPageCount = remainder == 0 ? quotient : quotient + 1;
for (int i = 0; i < mPageCount; i++) {
// 創(chuàng)建一個布局
LinearLayout container = createContainer();
if (i == mPageCount - 1) {
mUpLimited = remainder == 0 ? mPageSize : remainder;
}
for (int n = 0; n < mUpLimited; n++) {
TextView textView = createTextView(array.get(mPageSize * i + n));
container.addView(textView);
}
// 添加到分頁中
mRollingPages.add(container);
this.addView(container);
}
// 初始化顯示第一頁
mCurrentPage = 0;
mRollingPages.get(mCurrentPage).setVisibility(VISIBLE);
this.setVisibility(mRollingPages.get(mCurrentPage));
}
/**
* 創(chuàng)建頁對象
*
* @return
*/
private LinearLayout createContainer() {
if (mFrameParams == null) {
mFrameParams = new LayoutParams(MATCH_PARENT, WRAP_CONTENT);
mFrameParams.gravity = Gravity.CENTER_VERTICAL;
}
LinearLayout container = new LinearLayout(getContext());
container.setLayoutParams(mFrameParams);
container.setOrientation(LinearLayout.VERTICAL);
return container;
}
private void setVisibility(LinearLayout container) {
int count = container.getChildCount();
for (int i = 0; i < count; i++) {
container.getChildAt(i).setVisibility(VISIBLE);
}
}
/**
* 創(chuàng)建頁內(nèi)容對象
*
* @param text
* @return
*/
private TextView createTextView(String text) {
if (mLinearParams == null) {
mLinearParams = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
mLinearParams.gravity = Gravity.CENTER_VERTICAL;
}
TextView textView = new TextView(getContext());
textView.setLayoutParams(mLinearParams);
textView.setSingleLine();
textView.setPadding(mTextPadding, mTextPadding, mTextPadding, mTextPadding);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setTextColor(mTextColor);
textView.setVisibility(INVISIBLE);
textView.setText(text);
if (mLeftDrawable > 0) {
Drawable drawable = getContext().getResources().getDrawable(mLeftDrawable);
// Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), mLeftDrawable);
// Drawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
drawable.setBounds(0, 0, 10, 10);
textView.setCompoundDrawablePadding(10);
textView.setCompoundDrawables(drawable, null, null, null);
}
textView.setOnClickListener(this);
// 設(shè)置字體大小
if (mTextSize > 0) {
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
}
return textView;
}
private void createEnterAnimation() {
mEnterAnimSet = new AnimationSet(false);
TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, 0, TranslateAnimation.RELATIVE_TO_PARENT, 1f, TranslateAnimation.RELATIVE_TO_SELF, 0f);
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
mEnterAnimSet.addAnimation(translateAnimation);
mEnterAnimSet.addAnimation(alphaAnimation);
mEnterAnimSet.setDuration(ANIMATION_DURATION);
}
private void createExitAnimation() {
mExitAnimSet = new AnimationSet(false);
TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, 0, TranslateAnimation.RELATIVE_TO_SELF, 0f, TranslateAnimation.RELATIVE_TO_PARENT, -1f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
mExitAnimSet.addAnimation(translateAnimation);
mExitAnimSet.addAnimation(alphaAnimation);
mExitAnimSet.setDuration(ANIMATION_DURATION);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
pause();
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
resume();
break;
}
return true;
}
public void resume() {
// 只有一頁時不進行切換
if (mPageCount < 1) return;
if (mRunnable == null) {
mRunnable = new RollingRunnable();
} else {
mHandler.removeCallbacks(mRunnable);
}
mHandler.postDelayed(mRunnable, mDuration);
}
public void pause() {
if (mRunnable != null) {
mHandler.removeCallbacks(mRunnable);
}
}
@Override
public void onClick(View v) {
if (null == mClickListener) return;
TextView textView = (TextView) v;
mClickListener.onItemClick(textView);
textView.setTextColor(mClickColor);
}
/**
* 隱藏當(dāng)前頁,顯示下一頁任務(wù)
*/
public class RollingRunnable implements Runnable {
@Override
public void run() {
// 隱藏當(dāng)前頁
LinearLayout currentView = mRollingPages.get(mCurrentPage);
currentView.setVisibility(INVISIBLE);
if (mExitAnimSet != null) {
currentView.startAnimation(mExitAnimSet);// mExitUpAnim);
}
mCurrentPage++;
if (mCurrentPage >= mPageCount) {
mCurrentPage = 0;
}
// 顯示下一頁
LinearLayout nextView = mRollingPages.get(mCurrentPage);
nextView.setVisibility(VISIBLE);
setVisibility(nextView);
if (mEnterAnimSet != null) {
nextView.startAnimation(mEnterAnimSet);// mEnterDownAnim);
}
mHandler.postDelayed(this, mDuration);
}
}
public class Rotate3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final boolean mTurnIn;
private final boolean mTurnUp;
private float mCenterX;
private float mCenterY;
private Camera mCamera;
public Rotate3dAnimation(float fromDegrees, float toDegrees, boolean turnIn, boolean turnUp) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mTurnIn = turnIn;
mTurnUp = turnUp;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
mCenterY = getHeight() / 2;
mCenterX = getWidth() / 2;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final int derection = mTurnUp ? 1 : -1;
final Matrix matrix = t.getMatrix();
camera.save();
if (mTurnIn) {
camera.translate(0.0f, derection * mCenterY * (interpolatedTime - 1.0f), 0.0f);
} else {
camera.translate(0.0f, derection * mCenterY * (interpolatedTime), 0.0f);
}
camera.rotateX(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
public interface onItemClickListener {
void onItemClick(TextView v);
}
}
使用
// 初始化號外列表
List<String> haowaiArray = new ArrayList<>();
haowaiArray.add("[母嬰天地] 買尿不濕送嬰兒手口濕巾");
haowaiArray.add("[利民商店] 滿100免費配送");
haowaiArray.add("[果之家] 泰國金枕榴蓮8元/kg");
haowaiArray.add("[戶外運動] 戶外運動專業(yè)裝備搜集");
haowaiArray.add("[天天特價] 只要9.9還包郵");
haowaiArray.add("[尖端潮品] 折疊電動車");
haowaiArray.add("[黑科技] 智能VR帶你裝13");
haowaiArray.add("[旅行必備] 太陽能充電寶-永不斷電");
// 綁定數(shù)據(jù)
mRollingView.setPageSize(4);
mRollingView.setClickColor(0xff888888);
mRollingView.setLeftDrawable(R.drawable.drawable_red_dot);
mRollingView.setRollingText(haowaiArray);
mRollingView.setOnItemClickListener(this);
...
@Override
public void onItemClick(TextView v) {
// handle item click event
}
@Override
public void onResume() {
super.onResume();
mRollingView.resume();
}
@Override
public void onPause() {
super.onPause();
mRollingView.pause();
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實現(xiàn)加載廣告圖片和倒計時的開屏布局
- Android利用ViewPager實現(xiàn)滑動廣告板實例源碼
- Android實現(xiàn)Banner界面廣告圖片循環(huán)輪播(包括實現(xiàn)手動滑動循環(huán))
- Android自定義View實現(xiàn)廣告信息上下滾動效果
- Android筆記之:App應(yīng)用之發(fā)布各廣告平臺版本的詳解
- Android實現(xiàn)廣告圖片輪播效果
- Android編程實現(xiàn)ListView頭部ViewPager廣告輪詢圖效果
- Android 破解視頻App去除廣告功能詳解及解決辦法總結(jié)
- Android 應(yīng)用啟動歡迎界面廣告的實現(xiàn)實例
- Android開啟新線程實現(xiàn)電子廣告牌項目
相關(guān)文章
Android平臺下輕量級http網(wǎng)絡(luò)傳輸庫
這篇文章主要介紹了Android平臺下輕量級http網(wǎng)絡(luò)傳輸庫的相關(guān)資料,需要的朋友可以參考下2016-01-01
詳解Android中常見的內(nèi)存優(yōu)化及內(nèi)存泄露場景
本文主要給大家介紹了Android中常見的內(nèi)存優(yōu)化及Android開發(fā)中容易造成內(nèi)存泄露的場景,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-08-08
Android開啟閃光燈的方法 Android打開手電筒功能
這篇文章主要為大家詳細介紹了Android開啟閃光燈的方法,Android打開手電筒功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
Android基于OpenGL在GLSurfaceView上繪制三角形及使用投影和相機視圖方法示例
這篇文章主要介紹了Android基于OpenGL在GLSurfaceView上繪制三角形及使用投影和相機視圖方法,結(jié)合實例形式分析了Android基于OpenGL的圖形繪制技巧,需要的朋友可以參考下2016-10-10
AndroidHttpClient詳解及調(diào)用示例
本文給大家介紹AndroidHttpClient結(jié)構(gòu)、使用方式及調(diào)用示例詳解,需要的朋友可以參考下2015-10-10
Android開發(fā)中總結(jié)的Adapter工具類【附完整源碼下載】
這篇文章主要介紹了Android開發(fā)中總結(jié)的Adapter工具類,簡單說明了Adapter的功能,并結(jié)合實例形式分析了Adapter工具類的相關(guān)使用方法,并附帶完整源碼供讀者下載參考,需要的朋友可以參考下2017-11-11

