多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 氣泡隨機分布界面的實現

氣泡隨機分布界面的實現

來源:程序員人生   發布時間:2015-05-06 09:19:35 閱讀次數:3708次

        空話不多說,最近需求要實現1個這樣的界面,以下圖:


        整體界面要求為氣泡大致位置在屏幕某個區域,總數固定為8個,但圓心本身位置在該區域內隨機,氣泡半徑,背風景也隨機。然后界面展現時有1個漂浮出來的動畫效果,氣泡之間可以有遮擋但不可以擋住字,點擊換1批的時候,重復以上所述動畫效果,所有隨機值刷新。

        先做1個圓形的帶陰影的ImageView:代碼以下

package com.amuro.ballonlayout; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.Animator.AnimatorListener; import com.nineoldandroids.animation.AnimatorSet; import com.nineoldandroids.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.FontMetrics; import android.util.AttributeSet; import android.widget.ImageView; import android.widget.RelativeLayout.LayoutParams; public class BallonImageView extends ImageView { private static final int SHADOW_RATIO = 14; private Paint paintBkg; private Paint paintText; public BallonImageView(Context context) { this(context, null); } public BallonImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BallonImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { paintBkg = new Paint(); paintText = new Paint(); paintBkg.setStyle(Paint.Style.FILL); paintBkg.setAntiAlias(true); paintText.setColor(Color.WHITE); paintText.setStyle(Paint.Style.STROKE); paintText.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawShadow(canvas); drawCircleBkg(canvas); drawText(canvas); } private void drawShadow(Canvas canvas) { int viewWidth = getWidth(); int offsetX = viewWidth / SHADOW_RATIO; int cx = (viewWidth + offsetX) / 2; int cy = cx; int radius = (viewWidth - offsetX) / 2; paintBkg.setColor(Color.parseColor("#E1E1E1")); canvas.drawCircle(cx, cy, radius, paintBkg); } private void drawCircleBkg(Canvas canvas) { int viewWidth = getWidth(); int offsetX = viewWidth / SHADOW_RATIO; int cx = (viewWidth - offsetX) / 2; int cy = cx; int radius = cx; paintBkg.setColor(bkgColor); canvas.drawCircle(cx, cy, radius, paintBkg); } private void drawText(Canvas canvas) { int viewWidth = getWidth(); int offsetX = viewWidth / SHADOW_RATIO; int cx = (viewWidth - offsetX) / 2; int cy = cx; int textSize = getWidth() / 5; paintText.setTextSize(textSize); float textWidth = paintText.measureText(text); FontMetrics fm = paintText.getFontMetrics(); int textHeight = (int) Math.ceil(fm.descent - fm.top) + 2; canvas.drawText(text, cx - (textWidth / 2), cy + (textHeight / 4), paintText); } private String text = "測試測試"; private int bkgColor = Color.BLACK; public void setBkgColorAndText(int bkgColor, String text) { this.bkgColor = bkgColor; this.text = text; invalidate(); } public void setRadius(int radius) { int diameter = radius * 2; LayoutParams params = new LayoutParams(diameter, diameter); setLayoutParams(params); } public void floatToPosition(int startX, int startY, int toX, int toY, int duration) { AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(this, "translationX", startX, toX).setDuration(duration), ObjectAnimator.ofFloat(this, "translationY", startY, toY).setDuration(duration), ObjectAnimator.ofFloat(this, "scaleX", 0f, 1f), ObjectAnimator.ofFloat(this, "scaleY", 0f, 1f)); set.setDuration(duration).start(); set.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator arg0) { setEnabled(false); } @Override public void onAnimationRepeat(Animator arg0) { } @Override public void onAnimationEnd(Animator arg0) { setEnabled(true); } @Override public void onAnimationCancel(Animator arg0) { } }); } }


         BallonImageView主要做3件事 畫氣泡,畫陰影,畫字,畫好以后還對外提供1個漂浮的動畫的函數,本來這個函數我寫在Activity里讓Activity自己控制的,后來想一想根據

單1職責,氣泡自己的浮動效果是它自己邏輯,所以應當是它自己對外暴露方法,否則其他Activity需要這個動畫效果的時候,就會產生重復代碼了。

        下面設置1個BallonLayout來放置這些氣泡,邏輯比較復雜,大家自己看代碼吧,寫得好蛋疼……

package com.amuro.ballonlayout; import java.util.Random; import com.amuro.balloonlayout.R; import com.amuro.utils.DisplayUtils; import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; public class BallonLayout extends FrameLayout { private static final int BALLON_COUNT = 8; private static final String[] ballonColors = { "#f29b76", "#84ccc9", "#f8b551", "#88abda", "#89c997", "#eb6877", "#f39800", "#aa89bd" }; /***********監聽器相干***************/ private OnBallonClickListener onBallonClickListener; public interface OnBallonClickListener { public void onBallonClick(int id); } public void setOnBallonClickListener(OnBallonClickListener onBallonClickListener) { this.onBallonClickListener = onBallonClickListener; } private void notifyListener(int id) { if(this.onBallonClickListener != null) { this.onBallonClickListener.onBallonClick(id); } } /***********界面相干******************/ private Random random; //全局值 private int displayWidth; private int ballonFloatStartX; private int ballonFloatStartY; //過渡值 private int imageView1NowYUsed; private int imageView3ToX; private int imageView3Radius; private BallonImageView imageView1; private BallonImageView imageView2; private BallonImageView imageView3; private BallonImageView imageView4; private BallonImageView imageView5; private BallonImageView imageView6; private BallonImageView imageView7; private BallonImageView imageView8; public BallonLayout(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.ballon_layout, this); initPoints(); initView(); } private void initPoints() { random = new Random(); displayWidth = DisplayUtils.getDisplayWidth(getContext()); ballonFloatStartX = DisplayUtils.getDisplayWidth(getContext()) / 2; ballonFloatStartY = DisplayUtils.getDisplayHeight(getContext()); } private void initView() { imageView1 = (BallonImageView)findViewById(R.id.iv1); imageView2 = (BallonImageView)findViewById(R.id.iv2); imageView3 = (BallonImageView)findViewById(R.id.iv3); imageView4 = (BallonImageView)findViewById(R.id.iv4); imageView5 = (BallonImageView)findViewById(R.id.iv5); imageView6 = (BallonImageView)findViewById(R.id.iv6); imageView7 = (BallonImageView)findViewById(R.id.iv7); imageView8 = (BallonImageView)findViewById(R.id.iv8); imageView1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(0); } }); imageView2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(1); } }); imageView3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(2); } }); imageView4.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(3); } }); imageView5.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(4); } }); imageView6.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(5); } }); imageView7.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(6); } }); imageView8.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { notifyListener(7); } }); } public void setView(String[] ballonNames) { getNonredundantArray(); setImageView1(ballonNames[0]); setImageView2(ballonNames[1]); setImageView3(ballonNames[2]); setImageView4(ballonNames[3]); setImageView5(ballonNames[4]); setImageView6(ballonNames[5]); setImageView7(ballonNames[6]); setImageView8(ballonNames[7]); } private void setImageView1(String ballonName) { int toX = getBallonToX(displayWidth / 16, displayWidth / 8); int radius = getBallon1Radius(toX); imageView1.setRadius(radius); imageView1.setBkgColorAndText(getRandomColor(0), ballonName); imageView1.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, 100, getRandomDuration()); imageView1NowYUsed = radius * 2 + 100; } private int getBallon1Radius(int toX) { int maxRadius = (displayWidth / 2 - toX) / 2; int radius = (int) (maxRadius * getRadiusRange(0.8f, 0.85f)); return radius; } private void setImageView2(String ballonName) { int toX = getBallonToX((displayWidth / 8) * 5, (displayWidth / 4) * 3); int radius = getBallon2Radius(toX); imageView2.setRadius(radius); imageView2.setBkgColorAndText(getRandomColor(1), ballonName); imageView2.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, 40, getRandomDuration()); } private int getBallon2Radius(int toX) { int maxRadius = (displayWidth - toX) / 2; int radius = (int) (maxRadius * getRadiusRange(0.7f, 0.8f)); return radius; } private void setImageView3(String ballonName) { imageView3ToX = getBallonToX((displayWidth / 16) * 5, (displayWidth / 16) * 7); imageView3Radius = getBallon3Radius(); int toY = imageView1NowYUsed + 20; imageView3.setRadius(imageView3Radius); imageView3.setBkgColorAndText(getRandomColor(2), ballonName); imageView3.floatToPosition(ballonFloatStartX, ballonFloatStartY, imageView3ToX, toY, getRandomDuration()); imageView1NowYUsed = toY + imageView3Radius * 2; } private int getBallon3Radius() { int maxRadius = displayWidth / 8; int radius = (int) (maxRadius * getRadiusRange(0.85f, 0.95f)); return radius; } private void setImageView4(String ballonName) { int toX = getBallonToX(imageView3ToX + imageView3Radius * 2 + 30, (displayWidth / 4) * 3); int radius = getBallon4Radius(); int toY = imageView1NowYUsed - imageView3Radius * 2; imageView4.setRadius(radius); imageView4.setBkgColorAndText(getRandomColor(3), ballonName); imageView4.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, toY, getRandomDuration()); } private int getBallon4Radius() { int maxRadius = (displayWidth / 16) * 3; int radius = (int) (maxRadius * getRadiusRange(0.8f, 0.95f)); return radius; } private void setImageView5(String ballonName) { int toX = getBallonToX(displayWidth / 16, displayWidth / 8); int radius = getBallon3Radius(); int toY = imageView1NowYUsed + 10; imageView5.setRadius(radius); imageView5.setBkgColorAndText(getRandomColor(4), ballonName); imageView5.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, toY, getRandomDuration()); imageView1NowYUsed = imageView1NowYUsed + radius * 2; } private void setImageView6(String ballonName) { int toX = getBallonToX((displayWidth / 16) * 6, (displayWidth / 16) * 8); int radius = getBallon3Radius(); int toY = imageView1NowYUsed - radius; imageView6.setRadius(radius); imageView6.setBkgColorAndText(getRandomColor(5), ballonName); imageView6.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, toY, getRandomDuration()); imageView1NowYUsed = toY + radius * 2; } private void setImageView7(String ballonName) { int toX = getBallonToX((displayWidth / 16) * 11, (displayWidth / 16) * 12); int radius = getBallon3Radius(); int toY = imageView1NowYUsed - radius; imageView7.setRadius(radius); imageView7.setBkgColorAndText(getRandomColor(6), ballonName); imageView7.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, toY, getRandomDuration()); imageView1NowYUsed = toY + radius * 2; } private void setImageView8(String ballonName) { int toX = getBallonToX(displayWidth / 8, (displayWidth / 16) * 4); int radius = getBallon8Radius(); int toY = imageView1NowYUsed - radius; imageView8.setRadius(radius); imageView8.setBkgColorAndText(getRandomColor(7), ballonName); imageView8.floatToPosition(ballonFloatStartX, ballonFloatStartY, toX, toY, getRandomDuration()); } private int getBallon8Radius() { int maxRadius = (displayWidth / 24) * 4; int radius = (int) (maxRadius * getRadiusRange(0.8f, 0.95f)); return radius; } private int getBallonToX(int start, int end) { int toX = random.nextInt(end); if(toX < start) { toX = start; } return toX; } private float getRadiusRange(float minRange, float maxRange) { float range = random.nextFloat(); if(range <= minRange) { range = minRange; } if(range >= maxRange) { range = maxRange; } return range; } private int[] colorIndex = new int[BALLON_COUNT]; private int getRandomColor(int index) { return Color.parseColor(ballonColors[colorIndex[index]]); } private int getRandomDuration() { float seconds = (random.nextInt(50) + 51) / 100f; return (int) (seconds * 2000); } private void getNonredundantArray() { // 初始化備選數組 int[] defaultNums = new int[BALLON_COUNT]; for (int i = 0; i < defaultNums.length; i++) { defaultNums[i] = i; } // 默許數組中可以選擇的部份長度 int canBeUsed = BALLON_COUNT; // 填充目標數組 for (int i = 0; i < colorIndex.length; i++) { // 將隨機選取的數字存入目標數組 int index = random.nextInt(canBeUsed); colorIndex[i] = defaultNums[index]; // 將已用過的數字扔到備選數組最后,并減小可選區域 swap(index, canBeUsed - 1, defaultNums); canBeUsed--; } } private void swap(int i, int j, int[] nums) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } }


        其中的getNonredundantArray()通過洗牌算法,保證每次生成1個1⑻不重復的隨機數組,然后再從色彩數組當選擇出不同的色彩。監聽器的目的是告知監聽者哪一個氣泡被點擊了~ 終究代碼實現效果以下:

         還真是沒在網上找到類似的demo或例子,算是1次純原創的嘗試吧,謝謝各位觀賞~

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 免费a一级毛片在线播放 | 国产欧美久久精品 | 亚洲精品一区二区观看 | 国产福利一区在线 | 国产高清乱码无卡女大生 | 国产精品成人久久久久 | 免费看逼逼 | jizz在亚洲 | 国产一区二区三区免费看 | 亚洲人在线视频 | 91 色| 国产人成精品午夜在线观看 | 亚洲一区二区三区在线网站 | 日韩亚洲欧美性感视频影片免费看 | 日本免费一区二区三区最新vr | 国内成人精品亚洲日本语音 | 日韩精品亚洲精品485页 | 欧美成人h版网址 | 中文字幕精品视频 | 国产精品久久久久一区二区三区 | 亚洲不卡视频 | 精品毛片 | 久久久久久国产精品视频 | 男女性免费视频观看 | 国产日韩在线观看视频 | 日本怡春院欧美一区二区三区 | 亚洲色图色| 欧洲久久 | 精品视频在线观看 | 最近最好的中文字幕免费 | 可以免费观看全网 | 精品卡通动漫在线观看视频一区 | h在线观看视频免费网站 | 17videosex性欧美 | 在线亚洲精品国产成人二区 | 午夜精品久久久久久久久 | 超清中文乱码精品字幕在线观看 | 91精品欧美一区二区综合在线 | 国产色a在线观看 | yellow中文字幕在线高清 | 欧美一级毛片欧美大尺度一级毛片 |