中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android漂浮背景效果的制作方法

發布時間:2020-10-13 09:46:44 來源:腳本之家 閱讀:134 作者:大苞米 欄目:移動開發

GIF動圖效果不是很好,實際效果非常平滑very smooth,而且添加不同的圖形可以組成各種效果,目前已經用在我們項目的注冊界面~

Android漂浮背景效果的制作方法

原理:

實現原理很簡單,每一個懸浮的“小物體”就是一個自定義View,這些小的自定義View都盛放在一個自定義的ViewGroup中。然后所有的視圖都放在這個ViewGroup之上,這樣就相當于做一個可動的背景。

下面結合代碼詳細介紹下:

詳解:

FloatObject

懸浮的物體,繼承自View,需要重寫onDraw方法,主要作用就是來畫出自己,并進行隨機曲線運動。

任何需要畫出的對象都需要繼承FloatObject,并重寫提供的drawFloatObject方法,在此方法中可以通過設置畫筆和畫布畫出任意圖形。比如下面是畫出一行文字:

public class FloatText extends FloatObject {
 String text;

 public FloatText(float posX, float posY, String text) {
 super(posX, posY);
 this.text = text;
 setAlpha(88);
 setColor(Color.WHITE);
 }

 @Override
 public void drawFloatObject(Canvas canvas, float x, float y, Paint paint) {
 paint.setTextSize(65);
 canvas.drawText(text, x, y, paint);
 }
}

隨機曲線:

其實最復雜的部分就是讓漂浮的物體做隨機無規則的曲線運動,并且每個漂浮物的速度不同,這樣整個漂浮動畫才更加自然。

我之前想過使用布朗運動,但是在網上找了好久也沒找到一個好用的算法。

最后只能還是使用3點賽貝爾曲線,使漂浮物沿著一條賽貝爾曲線運動,達到終點時,再隨機產生一條新的曲線,這樣就可以實現隨機曲線運動了。

控制運動的代碼如下:

public void drawFloatItem(Canvas canvas) {

 switch (status) {
  case START:
  // fade in
  if (isFade() && alpha <= ALPHA_LIMIT) {
   paint.setAlpha(alpha);
   alpha += ALPHA_PER_FRAME;
  } else {
   setStatus(MOVE);
  }
  break;
  case MOVE:
  // 更新賽貝爾曲線點
  if (mCurDistance == 0) {
   start = new PointF(x, y);
   end = getRandomPoint((int)start.x, (int)start.y, (int) distance);// 取值范圍distance
   c1 = getRandomPoint((int)start.x, (int)start.y, random.nextInt(width / 2)); // 取值范圍width/2
   c2 = getRandomPoint(end.x, end.y, random.nextInt(width / 2));// 取值范圍width/2
  }

  // 計算塞貝兒曲線的當前點
  PointF bezierPoint = CalculateBezierPoint(mCurDistance / distance, start, c1, c2, end);
  x = bezierPoint.x;
  y = bezierPoint.y;

  // 更新當前路徑
  mCurDistance += MOVE_PER_FRAME;

  // 一段畫完后重置
  if (mCurDistance >= distance) {
   mCurDistance = 0;
  }
  break;
  case END:
  // fade out
  if (isFade() && alpha > 0) {
   paint.setAlpha(alpha);
   alpha -= ALPHA_PER_FRAME;
  } else {
   setStatus(FINISH);
  }
  break;
 }

 if (status != FINISH) {
  Log.e("drawFloatObject", x+", "+y);
  drawFloatObject(canvas, x ,y, paint);
 }
 }

關于賽貝爾曲線運動的算法都是復用之前寫的一篇文章ANDROID模擬火花粒子的滑動噴射效果,如果大家有興趣可以看看。

FloatBackground

FloatBackground繼承自FrameLayout,里面有一個用于存放FloatObject的集合。
FloatBackground的主要作用就是繪制所有的“漂浮物”,以及維護其生命周期:

初始化:

 private void initFloatObject(int width, int height) {
 for (FloatObject floatObject : floats) {
  int x = (int) (floatObject.posX * width);
  int y = (int) (floatObject.posY * height);
  floatObject.init(x, y, width, height);
 }
 }

繪制:

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 for (FloatObject floatObject : floats) {
  floatObject.drawFloatItem(canvas);
 }
 // 隔一段時間重繪一次, 動畫效果
 getHandler().postDelayed(runnable, DELAY);

 }

 // 重繪線程
 private Runnable runnable = new Runnable() {
 @Override
 public void run() {
  invalidate();
  // 控制幀數
 }
 };

開始和結束:

 public void startFloat() {
 for (FloatObject floatObject : floats) {
  floatObject.setStatus(FloatObject.START);
 }
 }

 public void endFloat() {
 for (FloatObject floatObject : floats) {
  floatObject.setStatus(FloatObject.END);
 }
 }

使用

使用時非常簡單,在layout文件中將FloatBackground設置為最底層的視圖(其實就是當作一個背景):

 <com.dean.library.FloatBackground
 android:id="@+id/float_view"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <LinearLayout
  android:layout_gravity="center"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">

  <Button
  android:id="@+id/start"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:text="Start" />

  <Button
  android:id="@+id/end"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="center"
  android:text="End" />
 </LinearLayout>
 </com.dean.library.FloatBackground>

在代碼中進行如下調用:

final FloatBackground floatBackground = (FloatBackground) this.findViewById(R.id.float_view);

 Button start = (Button) this.findViewById(R.id.start);
 start.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  floatBackground.startFloat();
  }
 });

 Button end = (Button) this.findViewById(R.id.end);
 end.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  floatBackground.endFloat();
  }
 });

 floatBackground.addFloatView(new FloatRect(0.2f, 0.3f, 30, 40));
 floatBackground.addFloatView(new FloatBitmap( this, 0.2f, 0.3f, R.drawable.gr_ptn_03));
 floatBackground.addFloatView(new FloatCircle( 0.8f, 0.8f));
 floatBackground.addFloatView(new FloatText( 0.3f, 0.6f, "E"));
 floatBackground.addFloatView(new FloatRing( 0.6f, 0.2f, 15 ,20));

浮物”時:floatBackground.addFloatView(new FloatText( 0.3f, 0.6f, “E”))
接收的三個參數分別為出生位置在屏幕寬的百分比,長的百分比,和顯示的文字。

Github

https://github.com/a396901990/FloatBackground

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

屯门区| 高平市| 英吉沙县| 共和县| 孟州市| 仁寿县| 宜君县| 上林县| 湖州市| 沁源县| 武冈市| 平阳县| 定日县| 庐江县| 崇州市| 龙游县| 炉霍县| 陵水| 桓台县| 平利县| 巴里| 吉木萨尔县| 平顶山市| 吴桥县| 齐齐哈尔市| 石泉县| 墨玉县| 股票| 门源| 天全县| 昭觉县| 大关县| 钟山县| 龙州县| 同江市| 穆棱市| 密云县| 卢氏县| 南和县| 临夏市| 许昌县|