热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android实现IOS相机滑动控件

这篇文章主要为大家详细介绍了Android实现IOS相机滑动控件的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

IOS相比于Android,动画效果是一方面优势,IOS相机切换时滑动的动画很不错,看着是有一个3D的效果,而且变化感觉很自然。Android也可以通过Graphics下面的Camera可以实现3D效果,开始尝试着用这个做了一下,效果不理想,滑动之后各组文字之间的距离就变了,从立体空间来说这是合逻辑的,但是看着很别捏。IOS相机的滑动效果文字之间的间隔在滑动的时候是不变的。

后面通过调整TextView X方向的scale使文字看着紧凑一点,然后通过计算的距离的方式,在滑动的时候保持各组文字之间的间隔一致,最后实现的效果还是和IOS的有一定的差距。先上个效果图的。 

下面逐步来说下怎么实现:

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 

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, 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  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  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  0) {
  CustomViewL.this.post(new Runnable() {
   @Override
   public void run() {
   // TODO Auto-generated method stub
   AnimationRunningCount--;
   mCurrentItem = currentItemCopy;
   int lastItem = scroolToRight &#63; 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 


 
 
  
 
 
 
 

整个来说其实也不复杂,有好些数学计算,几何问题,效果也没达到iphone的效果,如果有大神有想法,可以指导下。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文详细介绍超文本标记语言(HTML)的基本概念与语法结构。HTML是构建网页的核心语言,通过标记标签描述页面内容,帮助开发者创建结构化、语义化的Web页面。 ... [详细]
  • 本文将带您了解Cocos家族的不同版本和分支,特别是Cocos Creator的发展历程及其核心特性,帮助初学者快速入门。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文介绍如何通过SQL查询从JDE(JD Edwards)系统中提取所有字典数据,涵盖关键表的关联和字段选择。具体包括F0004和F0005系列表的数据提取方法。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 高效解决应用崩溃问题!友盟新版错误分析工具全面升级
    友盟推出的最新版错误分析工具,专为移动开发者设计,提供强大的Crash收集与分析功能。该工具能够实时监控App运行状态,快速发现并修复错误,显著提升应用的稳定性和用户体验。 ... [详细]
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 非授权维修导致iPhone 8屏幕失灵:苹果新固件策略解析
    设备制造商通常希望用户通过官方或授权服务中心进行维修,以确保质量并保障收入。然而,对于消费者而言,价格更低、服务更便捷的非授权维修商更具吸引力。本文将探讨使用非授权服务商更换iPhone 8屏幕可能带来的问题及其背后的技术原因。 ... [详细]
  • Ulysses Mac v29:革新文本编辑与写作体验
    探索Ulysses Mac v29,这款先进的纯文本编辑器为Mac用户带来了全新的写作和编辑环境。它不仅具备简洁直观的界面,还融合了Markdown等标记语言的最佳特性,支持多种格式导出,并提供强大的组织和同步功能。 ... [详细]
  • 本文介绍了如何在Xcode中通过自定义文件模板来添加个性化的注释,以提高代码的可读性和维护性。具体步骤包括打开Xcode的应用包,定位到文件模板目录,并对相关文件进行编辑。 ... [详细]
  • 本文探讨了在iOS项目中导入MKNetworkKit库时遇到的常见问题及其解决方案。 ... [详细]
author-avatar
Aero-Maxwell
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有