編輯:關於Android編程
項目中需要用到類似公告欄的控件,能用的基本不支持多行顯示,於是只好自己動手,苦於沒有自定義過一個像樣的控件,借鑒Android公告條demo,實現了多行向上滾動的控件。在原控件基礎之上添加如下功能:
•傳入數據分頁顯示
•添加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; /** * 公告滾動區 * * @author 祁連山 * @version 1.0 * @date 2016-08-17 */ public class RollingView extends FrameLayout implements OnClickListener { // 默認動畫執行時間 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; // 默認每頁信息數 private int mPageSize = 3; // 最後一頁余數 private int mUpLimited = mPageSize; // 當前顯示頁碼 private int mCurrentPage = 0; // 總分頁數 private int mPageCount; // 左圖片 private int mLeftDrawable; // 分頁數據對象 private List<LinearLayout> mRollingPages; // 默認動畫 private AnimationSet mEnterAnimSet; private AnimationSet mExitAnimSet; private RollingRunnable mRunnable; private Handler mHandler; private onItemClickListener mClickListener; // 布局參數 private LayoutParams mFrameParams; private LinearLayout.LayoutParams mLinearParams; //mEnterDownAnim,mOutUp分別構成向下翻頁的進出動畫 private Rotate3dAnimation mEnterDownAnim; private Rotate3dAnimation mExitUpAnim; //mEnterUpAnim,mOutDown分別構成向下翻頁的進出動畫 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(); // 創建默認顯示隱藏動畫 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; } /** * 設置分頁大小 * * @param pageSize */ public void setPageSize(int pageSize) { this.mPageSize = this.mUpLimited = pageSize; } /** * 設置延遲時間 * * @param millionSeconds */ public void setDelayedDuration(long millionSeconds) { this.mDuration = millionSeconds; } /** * 設置顯示動畫 * * @param animation */ public void setEnterAnimation(AnimationSet animation) { mEnterAnimSet = animation; } /** * 設置隱藏動畫 * * @param animation */ public void setExitAnimation(AnimationSet animation) { mExitAnimSet = animation; } /** * 設置行距 * * @param padding */ public void setTextPadding(int padding) { this.mTextPadding = padding; } /** * 設置點擊後字體顏色 * * @param color */ public void setClickColor(int color) { this.mClickColor = color; } /** * 設置左圖片 * * @param drawable */ public void setLeftDrawable(int drawable) { this.mLeftDrawable = drawable; } /** * 設置點擊事件 * * @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); // 如果是未指定大小,那麼設置寬為300px int exceptWidth = 300; int exceptHeight = 0; // 計算高度,如果將高度設置為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(); // 計算商數 int quotient = array.size() / mPageSize; // 計算余數 int remainder = array.size() % mPageSize; // 計算需要創建多少頁 mPageCount = remainder == 0 ? quotient : quotient + 1; for (int i = 0; i < mPageCount; i++) { // 創建一個布局 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)); } /** * 創建頁對象 * * @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); } } /** * 創建頁內容對象 * * @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); // 設置字體大小 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); } /** * 隱藏當前頁,顯示下一頁任務 */ public class RollingRunnable implements Runnable { @Override public void run() { // 隱藏當前頁 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("[戶外運動] 戶外運動專業裝備搜集"); haowaiArray.add("[天天特價] 只要9.9還包郵"); haowaiArray.add("[尖端潮品] 折疊電動車"); haowaiArray.add("[黑科技] 智能VR帶你裝13"); haowaiArray.add("[旅行必備] 太陽能充電寶-永不斷電"); // 綁定數據 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(); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
從意圖返回結果 startActivity()方法調用另一個活動,但並沒有返回結果給當前活動。此時如想從一個活動中回傳數據,就要使用startActivityFo
摘要:Json數據在安卓開發過程中是非常常見的,在請求服務器端數據的時候,服務器端返回的無非就是三種類型:HTML,XML,JSON。所以學習JSON對安卓程序員來說是非
在學習使用Scroller之前,需要明白scrollTo()、scrollBy()方法。一、View的scrollTo()、scrollBy()scrollTo、scro
四大組件的運行狀態: Android中的四大組件中除了BroadcastReceiver以外,其他三種組件都必須在Android Mainfrst中注冊。對於,Bro