国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android實(shí)現(xiàn)IOS相機(jī)滑動(dòng)控件

2019-12-12 05:50:09
字體:
供稿:網(wǎng)友

IOS相比于Android,動(dòng)畫效果是一方面優(yōu)勢(shì),IOS相機(jī)切換時(shí)滑動(dòng)的動(dòng)畫很不錯(cuò),看著是有一個(gè)3D的效果,而且變化感覺很自然。Android也可以通過Graphics下面的Camera可以實(shí)現(xiàn)3D效果,開始嘗試著用這個(gè)做了一下,效果不理想,滑動(dòng)之后各組文字之間的距離就變了,從立體空間來說這是合邏輯的,但是看著很別捏。IOS相機(jī)的滑動(dòng)效果文字之間的間隔在滑動(dòng)的時(shí)候是不變的。

后面通過調(diào)整TextView X方向的scale使文字看著緊湊一點(diǎn),然后通過計(jì)算的距離的方式,在滑動(dòng)的時(shí)候保持各組文字之間的間隔一致,最后實(shí)現(xiàn)的效果還是和IOS的有一定的差距。先上個(gè)效果圖的。 

下面逐步來說下怎么實(shí)現(xiàn):

MainaActivity.java: 

往自定義的控件加了6個(gè)TextView,對(duì)應(yīng)各個(gè)模式。 

這里面還實(shí)現(xiàn)了一個(gè)手勢(shì)監(jiān)聽,來識(shí)別滑動(dòng)事件。對(duì)動(dòng)畫做了一些限制,角度小于30度,滑動(dòng)距離大于15才能生效。 

package com.example.androidcustomnview;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.util.Log;import android.view.GestureDetector;import android.view.GestureDetector.OnGestureListener;import android.view.View;import android.view.View.OnTouchListener;import android.view.MotionEvent;import android.view.TextureView;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.view.animation.AnimationSet;import android.view.animation.TranslateAnimation;import android.widget.FrameLayout;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;public class MainActivity extends Activity implements OnTouchListener{ private static final String TAG = "MainActivity.TAG"; CustomViewL mCustomViewL; String[] name = new String[] {"延時(shí)攝影","慢動(dòng)作","視頻","拍照","正方形","全景"}; GestureDetector mGestureDetector; RelativeLayout rootView; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  mCustomViewL = (CustomViewL) findViewById(R.id.mCustomView);  rootView = (RelativeLayout) findViewById(R.id.ViewRoot);  rootView.setOnTouchListener(this);  mCustomViewL.getParent();  mCustomViewL.addIndicator(name);  mGestureDetector = new GestureDetector(this, new myGestureDetectorLis()); 48  }  class myGestureDetectorLis implements GestureDetector.OnGestureListener {    private static final int degreeLimit = 30;  private static final int distanceLimit = 15;    private boolean isScroll = false;  @Override  public boolean onDown(MotionEvent e) {   // TODO Auto-generated method stub   Log.d(TAG, "myGestureDetectorLis onDown");   isScroll = false;   return true;  }  @Override  public void onShowPress(MotionEvent e) {   // TODO Auto-generated method stub     }  @Override  public boolean onSingleTapUp(MotionEvent e) {   // TODO Auto-generated method stub   return false;  }    @Override  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,    float distanceY) {   // TODO Auto-generated method stub   if (isScroll) return false;   double degree = Math.atan(Math.abs(e2.getY() - e1.getY()) / Math.abs(e2.getX() - e1.getX())) * 180 /Math.PI;   float delta = e2.getX() - e1.getX();   if (delta > distanceLimit && degree < degreeLimit) {    Log.d(TAG, "向右滑");    isScroll = true;    mCustomViewL.scrollRight();   } else if (delta < -distanceLimit && degree < degreeLimit) {    Log.d(TAG, "向左滑");    isScroll = true;    mCustomViewL.scrollLeft();   }   return false;  }    @Override  public void onLongPress(MotionEvent e) {   // TODO Auto-generated method stub     }  @Override  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    float velocityY) {   // TODO Auto-generated method stub   return false;  }   } @Override public boolean onTouch(View v, MotionEvent event) {  // TODO Auto-generated method stub  return mGestureDetector.onTouchEvent(event); }}

CustomViewL.java:

自定義的控件,繼承自LinearLayout。在onLayout里面,重新計(jì)算了下各個(gè)子控件的位置,因?yàn)楦鹘M文字的scale是不一樣的,必須重新Layout一下各個(gè)子控件的位置,是文字的顯示區(qū)域和點(diǎn)擊區(qū)域是一樣的,這樣給各個(gè)子控件設(shè)置的onClick事件才有效。

dispatchDraw方法是重繪各個(gè)子控件,更具各個(gè)子控件到中心控件的位置的距離,設(shè)置了各個(gè)TextView X方向的scale,為了就是看著要有一個(gè)立體的效果。

滑動(dòng)之后,開始一個(gè)動(dòng)畫,動(dòng)畫結(jié)束之后重新requestLayout一下,重新計(jì)算下各個(gè)控件的位置。這個(gè)可以連續(xù)滑動(dòng)的,如果這次動(dòng)畫在執(zhí)行,會(huì)保存一下,等動(dòng)畫完了之后會(huì)接著跑下一個(gè)動(dòng)畫。各個(gè)子控件滑動(dòng)距離的計(jì)算有興趣的可以自己研究下,這里就不贅述了,其實(shí)也是數(shù)學(xué)知識(shí)。 

package com.example.androidcustomnview;import android.content.Context;import android.graphics.Camera;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Shader;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.WindowManager;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.view.animation.TranslateAnimation;import android.widget.LinearLayout;import android.widget.TextView;public class CustomViewL extends LinearLayout { private static final String TAG = "CustomViewL.TAG"; private Matrix mMatrix; Camera mCamera; private int mCurrentItem = 2;  private int screenWidth; private Paint mPaint; public static final float ItemScale = 0.1f; public CustomViewL(Context context) {  super(context);  // TODO Auto-generated constructor stub  initView(context); }  public CustomViewL(Context context, AttributeSet attrs, int defStyleAttr,   int defStyleRes) {  super(context, attrs, defStyleAttr, defStyleRes);  initView(context); } public CustomViewL(Context context, AttributeSet attrs, int defStyleAttr) {  super(context, attrs, defStyleAttr);  initView(context); } public CustomViewL(Context context, AttributeSet attrs) {  super(context, attrs);  initView(context); }  private void initView(Context context) {  screenWidth = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE))    .getDefaultDisplay().getWidth(); }  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {  Log.d(TAG, "onLayout ");  super.onLayout(changed, l , t, r, b);  View v = getChildAt(mCurrentItem);  int delta = getWidth() / 2 - v.getLeft() - v.getWidth()/2;     for (int i = 0; i < getChildCount(); i++) {   View v1 = getChildAt(i);   if (i == mCurrentItem) {    v1.layout(v1.getLeft() + delta, v1.getTop(),      v1.getRight() + delta, v1.getBottom());    continue;   }   float mScale = Math.abs(i - mCurrentItem) * ItemScale;   int move = (int)(v1.getWidth() * mScale / 2);   if (i < mCurrentItem) {    for (int j = i + 1; j < mCurrentItem; j++) {     View v2 = getChildAt(j);     move += (int) (v2.getWidth() * Math.abs(j - mCurrentItem) * ItemScale);    }   } else {    for (int j = i - 1; j > mCurrentItem; j--) {     View v2 = getChildAt(j);     move += (int)(v2.getWidth() * Math.abs(j - mCurrentItem) * ItemScale);    }    move = -move;   }   v1.layout(v1.getLeft() + delta + move, v1.getTop(),      v1.getRight() + delta + move, v1.getBottom());  }  mRequstLayout = false; } @Override protected void dispatchDraw(Canvas canvas) {  int count = getChildCount();  for (int i = 0; i < count; i++) {   updateChildItem(canvas,i);  } }  public void updateChildItem(Canvas canvas,int item) {//  Log.d(TAG, "updateChildItem");  View v = getChildAt(item);    float desi = 1- Math.abs(item - mCurrentItem) * ItemScale;  ((TextView)v).setScaleX(desi);  drawChild(canvas, v, getDrawingTime());  updateTextColor();   }  private void updateTextColor() {  for (int i =0 ; i < getChildCount(); i++) {   if (i == mCurrentItem) {    ((TextView)getChildAt(i)).setTextColor(Color.YELLOW);   } else {    ((TextView)getChildAt(i)).setTextColor(Color.WHITE);   }  } }   boolean scroolToRight = false;  public void scrollRight() {  if (mRequstLayout) return;  if (mCurrentItem > 0) {   if (mAnimationRunning) {    if (AnimationRunningCount < 1) {     currentItemCopy = mCurrentItem - 1;     AnimationRunningCount++;     scroolToRight = true;    }    return;   }   mCurrentItem--;   startTraAnimation(mCurrentItem,mCurrentItem + 1);   updateTextColor();  } }  private int currentItemCopy; public void scrollLeft() {  if (mRequstLayout) return;  if (mCurrentItem < getChildCount() - 1) {   if (mAnimationRunning) {    if (AnimationRunningCount < 1) {     currentItemCopy = mCurrentItem + 1;     AnimationRunningCount++;     scroolToRight = false;    }    return;   }   mCurrentItem++;   startTraAnimation(mCurrentItem,mCurrentItem-1);   updateTextColor();  }  }  public void addIndicator(String[] name) {  for (int i=0; i< name.length; i++) {   TextView mTextView = new TextView(getContext());   mTextView.setText(name[i]);   mTextView.setTextColor(Color.WHITE);   mTextView.setLines(1);   LinearLayout.LayoutParams ll = new LinearLayout.LayoutParams(     LinearLayout.LayoutParams.WRAP_CONTENT,      LinearLayout.LayoutParams.WRAP_CONTENT);   ll.setMargins(20, 0, 20, 0);   addView(mTextView,ll);  } }  class myAnimationListener implements android.view.animation.Animation.AnimationListener {  @Override  public void onAnimationStart(Animation animation) {   Log.d(TAG, "onAnimationStart ");   mAnimationRunning = true;  }  @Override  public void onAnimationEnd(Animation animation) {   // TODO Auto-generated method stub   Log.d(TAG, "onAnimationEnd ");   for (int i= 0; i < getChildCount(); i++) {    getChildAt(i).clearAnimation();   }   mRequstLayout = true;   requestLayout();   mAnimationRunning = false;   if (AnimationRunningCount > 0) {    CustomViewL.this.post(new Runnable() {     @Override     public void run() {      // TODO Auto-generated method stub      AnimationRunningCount--;      mCurrentItem = currentItemCopy;      int lastItem = scroolToRight ? currentItemCopy + 1 : currentItemCopy - 1;      startTraAnimation(currentItemCopy,lastItem);      updateTextColor();     }    });   }  }  @Override  public void onAnimationRepeat(Animation animation) {  }   }  private int AnimitionDurationTime = 300; private int AnimationRunningCount = 0; private boolean mAnimationRunning = false; private boolean mRequstLayout = false; public void startTraAnimation(int item,int last) {  Log.d(TAG, "startTraAnimation item = " + item);  View v = getChildAt(item);  final int width = v.getWidth();  final int childCount = getChildCount();  int traslate = getWidth()/2 - v.getLeft() - width/2;    int currentItemWidthScale = (int) (width * ItemScale);  for (int i = 0; i < childCount; i++) {   int delta = currentItemWidthScale / 2;      Log.d(TAG, " i = " + i + " delta before = " + delta);    if (i < item) {    delta = -delta;    for (int j = i; j < item; j++) {     int a;     if (i == j) {      a = (int)(getChildAt(j).getWidth() * ItemScale / 2);     } else {      a = (int)(getChildAt(j).getWidth() * ItemScale);     }     delta = item < last ? delta - a : delta + a;    }   } else if (i > item){    for (int j = item + 1; j <= i; j++) {     int a;     if (j == i) {      a = (int)(getChildAt(j).getWidth() * ItemScale / 2);     } else {      a = (int)(getChildAt(j).getWidth() * ItemScale);     }     delta = item < last ? delta - a : delta + a;    }   } else {    delta = 0;   }   Log.d(TAG, "delta = " + delta);   delta += traslate;   TranslateAnimation translateAni = new TranslateAnimation(0, delta, 0, 0);   translateAni.setDuration(AnimitionDurationTime);   translateAni.setFillAfter(true);   if (i == item) translateAni.setAnimationListener(new myAnimationListener());   mAnimationRunning = true;   getChildAt(i).startAnimation(translateAni);  } }}

最后說一下布局文件,兩邊本來是要做一個(gè)陰影效果的,為了簡便,復(fù)習(xí)了下PS,就在上面蓋了張圖片,顯得兩邊有陰影。  

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.androidcustomnview.MainActivity" > <RelativeLayout  android:id="@+id/ViewRoot"  android:gravity="center"   android:layout_width="match_parent"  android:layout_height="match_parent">  <com.example.androidcustomnview.CustomViewL   android:orientation="horizontal"   android:background="@android:color/background_dark"   android:id="@+id/mCustomView"   android:layout_width="match_parent"   android:layout_height="wrap_content"   >     </com.example.androidcustomnview.CustomViewL>  <ImageView    android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:layout_alignLeft="@id/mCustomView"   android:layout_alignTop="@id/mCustomView"   android:layout_alignRight="@id/mCustomView"   android:layout_alignBottom="@id/mCustomView"   android:background="@drawable/test"/>   </RelativeLayout></RelativeLayout>

整個(gè)來說其實(shí)也不復(fù)雜,有好些數(shù)學(xué)計(jì)算,幾何問題,效果也沒達(dá)到iphone的效果,如果有大神有想法,可以指導(dǎo)下。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 西昌市| 腾冲县| 红桥区| 昌平区| 灵川县| 天峨县| 梁平县| 开平市| 嵊泗县| 杂多县| 锦屏县| 东城区| 米泉市| 芜湖县| 大竹县| 抚宁县| 福安市| 盐源县| 上蔡县| 湘潭县| 古田县| 治多县| 金乡县| 邹城市| 台湾省| 新巴尔虎右旗| 西贡区| 都匀市| 榆社县| 井研县| 金坛市| 宜川县| 平和县| 都兰县| 桑日县| 泰顺县| 宁德市| 平凉市| 房产| 中卫市| 株洲市|