大佬教程收集整理的这篇文章主要介绍了Android实现IOS相机滑动控件,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
IOS相比于Android,动画效果是一方面优势,IOS相机切换时滑动的动画很不错,看着是有一个3D的效果,而且变化感觉很自然。Android也可以通过Graphics下面的Camera可以实现3D效果,开始尝试着用这个做了一下,效果不理想,滑动之后各组文字之间的距离就变了,从立体空间来说这是合逻辑的,但是看着很别捏。IOS相机的滑动效果文字之间的间隔在滑动的时候是不变的。
后面通过调整TextView X方向的scale使文字看着紧凑一点,然后通过计算的距离的方式,在滑动的时候保持各组文字之间的间隔一致,最后实现的效果还是和IOS的有一定的差距。先上个效果图的。
下面逐步来说下怎么实现:
@H_836_16@mainaActivity.java:
往自定义的控件加了6个TextView,对应各个模式。
这里面还实现了一个手势监听,来识别滑动事件。对动画做了一些限制,角度小于30度,滑动距离大于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[] {"延时摄影","慢动作","视频","拍照","正方形","全景"}; 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,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里面,重新计算了下各个子控件的位置,因为各组文字的scale是不一样的,必须重新Layout一下各个子控件的位置,是文字的显示区域和点击区域是一样的,这样给各个子控件设置的onClick事件才有效。
dispatchDraw方法是重绘各个子控件,更具各个子控件到中心控件的位置的距离,设置了各个TextView X方向的scale,为了就是看着要有一个立体的效果。
滑动之后,开始一个动画,动画结束之后重新requestLayout一下,重新计算下各个控件的位置。这个可以连续滑动的,如果这次动画在执行,会保存一下,等动画完了之后会接着跑下一个动画。各个子控件滑动距离的计算有兴趣的可以自己研究下,这里就不赘述了,其实也是数学知识。
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,int defStyleAttr) { super(context,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.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,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); translateAni.setDuration(AnimitionDurationTimE); translateAni.setFillAfter(true); if (i == item) translateAni.setAnimationListener(new myAnimationListener()); mAnimationRunning = true; getChildAt(i).startAnimation(translateAni); } } }
最后说一下布局文件,两边本来是要做一个阴影效果的,为了简便,复习了下PS,就在上面盖了张图片,显得两边有阴影。
<RelativeLayout xmlns:android="http://scheR_87_11845@as.android.com/apk/res/android" xmlns:tools="http://scheR_87_11845@as.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>
整个来说其实也不复杂,有好些数学计算,几何问题,效果也没达到iphone的效果,如果有大神有想法,可以指导下。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
以上是大佬教程为你收集整理的Android实现IOS相机滑动控件全部内容,希望文章能够帮你解决Android实现IOS相机滑动控件所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。