本文实例为大家分享了android实现icon动态旋转效果的具体代码,供大家参考,具体内容如下

碰到客户的这样一个需求,点击icon后,前景的icon开始旋转,背景的icon不动,就是这样一个效果

通过第三方的方法是不可能实现的,我这里是通过修改系统launcher的代码来实现。实现思路是在launcher中找到显示icon图标代码,并把这个图标覆盖掉。很多第手机的时钟icon是可以动态变化的,好在公司已经有人实现这个功能,可以借鉴

我这里先把时钟动态icon的实现说明下,需要的朋友可以参考。

写一个IconScript的基类继承Drawable

package com.android.launcher3;
 
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.util.Log;
 
public class IconScript extends Drawable{  
    public boolean isRuning = false;  
    public FastBitmapDrawable mFastBitmapDrawable = null;  
    protected Paint mPaint = new Paint();  
      
    public IconScript(){  
        mPaint.setAntiAlias(true);   
        mPaint.setFilterBitmap(true);  
    }  
      
    public void draw(Canvas canvas){  
        if(mFastBitmapDrawable != null){  
            Log.e("fly","IconScript=");
            canvas.drawBitmap(mFastBitmapDrawable.getBitmap(), null, getBounds(),mPaint);//画底图  
        }  
    }  
      
    /** 
     * 运行脚本 
     * @param view 
     */  
    public void run(View view){  
        isRuning = true;  
    }  
      
    /** 
     * 停止脚本 
     * (未调用,暂留入口) 
     */  
    public void onStop(){  
        isRuning = false;  
    }  
      
    /** 
     * 暂停脚本 
     * (未调用,暂留入口) 
     */  
    public void onPause(){  
        isRuning = false;  
    }  
      
    /** 
     * 恢复脚本 
     * (未调用,暂留入口) 
     */  
    public void onResume(){  
        isRuning = true;  
    }  
  
    @Override  
    public int getOpacity() {  
        // TODO Auto-generated method stub  
        return 0;  
    }  
  
    @Override  
    public void setAlpha(int arg0) {  
        // TODO Auto-generated method stub  
          
    }  
  
    @Override  
    public void setColorFilter(ColorFilter arg0) {  
        // TODO Auto-generated method stub  
          
    }  
      
    @Override  
    public int getIntrinsicWidth() {  
        int width = getBounds().width();  
        if (width == 0) {  
            width = mFastBitmapDrawable.getBitmap().getWidth();  
        }  
        return width;  
    }  
  
    @Override  
    public int getIntrinsicHeight() {  
        int height = getBounds().height();  
        if (height == 0) {  
            height = mFastBitmapDrawable.getBitmap().getHeight();  
        }  
        return height;  
    }  
  
    @Override  
    public int getMinimumWidth() {  
        return getBounds().width();  
    }  
  
    @Override  
    public int getMinimumHeight() {  
        return getBounds().height();  
    }  
      
    @Override  
    public void setFilterBitmap(boolean filterBitmap) {  
        mPaint.setFilterBitmap(filterBitmap);  
        mPaint.setAntiAlias(filterBitmap);  
    }  
      
    public void setFastBitmapDrawable(FastBitmapDrawable drawable){  
        mFastBitmapDrawable = drawable;  
    }  
      
    public FastBitmapDrawable setFastBitmapDrawable(){  
        return mFastBitmapDrawable;  
    }  
}  

核心类ClockScript继承IconScript

package com.android.launcher3;
 
 
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.format.Time;
import android.view.View;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
 
 
 
 
public class ClockScript extends IconScript {  
   Rect mRect = null;  
   /** 
    * 效果展示目标View 
    */  
   private View mView;  
   /** 
    * 通知系统更新视图现成 
    */  
   private ClockThread mClockThread = null;  
   /** 
    * 当前是否显示在屏幕上 
    */  
   private boolean mIsShowInScreen = false;  
   Context mContext; 
 
 
   public ClockScript(Context context){  
       super();  
    mContext = context;  
   }  
   public void run(View view) {  
       mView = view;  
       mRect = getBounds();  
       if(mClockThread == null){  
           mClockThread = new ClockThread();  
           mClockThread.start();  
       }  
   }  
     
   @Override  
   public void onPause() {  
       mClockThread.pauseRun();  
       super.onPause();  
   }  
     
   @Override  
   public void onResume() {  
       mClockThread.resumeRun();  
       super.onResume();  
   }  
     
   @Override  
   public void onStop() {  
       mClockThread.stopRun();  
       super.onStop();  
   }  
     
 
   @Override  
   public void draw(Canvas canvas) {  
       super.draw(canvas);  
       mIsShowInScreen = true;  
 
 
       drawIndicator(canvas,mRect.centerX(),mRect.centerY(),mPaint);  
 
 
       if(mClockThread.wait){  
           mClockThread.resumeRun();  
       }  
   }  
   /** 
    * 画指针 
    * @param canvas 
    * @param centerX 
    * @param centerY 
    * @param p 
    */  
 private void drawIndicator(Canvas canvas,int centerX,int centerY,Paint p){  
         
    Bitmap clockIcon = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher_clock),mContext);  
 
 
 
    int X = clockIcon.getWidth()/2;
    int Y = clockIcon.getHeight()/2;
    canvas.drawBitmap(clockIcon, null, getBounds(),p);//画底图  
 
    Time t=new Time();
     t.setToNow(); 
    p.setAntiAlias(true);
    p.setStrokeWidth(3);
    p.setColor(Color.WHITE);
    p.setStyle(Paint.Style.FILL);
 
 
//hour
canvas.drawLine(X, Y, int)(X   (clockIcon.getWidth()/2-35) * Math.cos((t.hour (float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), (int)(Y   (clockIcon.getWidth()/2-35) * Math.sin((t.hour (float)t.minute/60) * (Math.PI / 6) - Math.PI / 2)), p);
//minute
canvas.drawLine(X, Y,(int)(X   (clockIcon.getWidth()/2-27) * Math.cos(t.minute * (Math.PI / 30) - Math.PI / 2)),(int)(Y   (clockIcon.getWidth()/2-27) * Math.sin(t.minute * (Math.PI / 30) - Math.PI / 2)),p);
//second
p.setColor(Color.RED);
p.setStrokeWidth(1);
p.setStyle(Paint.Style.FILL);
canvas.drawLine(X, Y,(int)(X   (clockIcon.getWidth()/2-20) * Math.cos(t.second * (Math.PI / 30) - Math.PI / 2)),(int)(Y   (clockIcon.getWidth()/2-20) * Math.sin(t.second * (Math.PI / 30) - Math.PI / 2)),p);
      
p.setColor(Color.WHITE);
canvas.drawCircle(X, Y, 4, p);
p.setColor(Color.GRAY);
canvas.drawCircle(X, Y, 2, p);
 
}  
     
   class ClockThread extends Thread {  
       int times = 0;  
       boolean running = true;  
 
       public boolean wait = false;  
 
       public void stopRun() {  
           running = false;  
           synchronized (this) {  
               this.notify();  
           }  
       };  
 
       public void pauseRun() {  
           this.wait = true;  
           synchronized (this) {  
               this.notify();  
           }  
       }  
 
       public void resumeRun() {  
           this.wait = false;  
           synchronized (this) {  
               this.notify();  
           }  
       }  
 
       public void run() {  
           while (running) {  
               synchronized (mView) {  
                   mView.postInvalidate();  
               }  
                 
               if(!mIsShowInScreen){  
                   pauseRun();  
               }  
               mIsShowInScreen = false;  
               try {  
                   Thread.sleep(500);  
               } catch (Exception e) {  
                   System.out.println(e);  
               }  
                 
               synchronized (this) {  
                   if (wait) {  
                       try {  
                           wait();  
                       } catch (InterruptedException e) {  
                           // TODO Auto-generated catch block  
                           e.printStackTrace();  
                       }  
                   }  
               }  
           }  
       }  
   }  
 
}  

接下来就是如何初始化这个ClockScript,在Icon类里面添加代码

--- a/packages/apps/Launcher3/src/com/android/launcher3/IconCache.java
    b/packages/apps/Launcher3/src/com/android/launcher3/IconCache.java
@@ -84,6  84,7 @@ public class IconCache {
         public CharSequence title = "";
         public CharSequence contentDescription = "";
         public boolean isLowResIcon;
         public IconScript script;
     }
 
     private final HashMap<UserHandleCompat, Bitmap> mDefaultIcons = new HashMap<>();
@@ -591,7  592,17 @@ public class IconCache {
        if (info != null) {
            entry.title = info.getLabel();
        }
-
       
        Log.e("IconCache ","componentName.getPackageName()=" componentName.getPackageName());
        //加了一个系统的属性来控制
        if(null != entry && componentName.getPackageName().equals("com.android.deskclock")  && android.os.SystemProperties.getBoolean("launcher.calender.updateicon", false))
        {        
           Log.e("IconCache","clock init");
            entry.script = new ClockScript(mContext);  
        }
 
         return entry;
     }
 
@@ -891,4  902,20 @@ public class IconCache {
             return null;
         }
     }
     public IconScript getScript(Intent intent, UserHandleCompat user){  
         synchronized (mCache) {  
              ComponentName component = intent.getComponent();  
             
              if (component == null) {  
                 Log.e("IconCache ","component==null");
                  return null;  
              }  
             LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);  
             CacheEntry entry = cacheLocked(component, launcherActInfo,user, false, false);  
             return entry.script;  
         }  
     }  

在BubbleTextView类中添加代码

--- a/packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java
    b/packages/apps/Launcher3/src/com/android/launcher3/BubbleTextView.java
@@ -30,6  30,7 @@ import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.KeyEvent;
@@ -38,6  39,7 @@ import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewParent;
 import android.widget.TextView;
 import android.graphics.Rect;
 
 import com.android.launcher3.IconCache.IconLoadRequest;
 import com.android.launcher3.model.PackageItemInfo;
@@ -148,12  150,44 @@ public class BubbleTextView extends TextView
 
     public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache) {
         applyFromShortcutInfo(info, iconCache, false);
-    }
         
         mScript = info.getScript(iconCache); //zengxiao add
         if(mScript!=null){
         if(mScript!=null){
         }else{
                Log.e("rtyre","info.iconResource.packageName ------null");
         }
     }
    private IconScript mScript;
     @Override  
     public void setCompoundDrawables(Drawable left, Drawable top,  
             Drawable right, Drawable bottom) {  
        
         if(top != null){  
              
             if(mScript != null){  
               
                 top = mScript;  
                 Rect rect=new Rect(0,0,LauncherAppState.getInstance().getInvariantDeviceProfile().iconBitmapSize,LauncherAppState.getInstanc
                 mScript.setBounds(rect);  
                          
                 if(!mScript.isRuning) 
                 {
                             
                                mScript.run(this);  
                 }
             }  
         }  
       
         super.setCompoundDrawables(left, top, right, bottom);  
     }  
 
     public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
             boolean promiseStateChanged) {
         Bitmap b = info.getIcon(iconCache);
-
         mScript = info.getScript(iconCache); 
         FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(b);
--- a/packages/apps/Launcher3/src/com/android/launcher3/ShortcutInfo.java
    b/packages/apps/Launcher3/src/com/android/launcher3/ShortcutInfo.java
@@ -304,5  304,13 @@ public class ShortcutInfo extends ItemInfo {
     public boolean isDisabled() {
         return isDisabled != 0;
     }
     
     
     public IconScript getScript(IconCache iconCache){  
         return iconCache.getScript(promisedIntent != null ? promisedIntent : intent, user);  
     }  
     
 }

把这些代码添加上功能基本ok.

有了这个基础,我想要实现的效果就变得很简单,同样的定义一个WallpaperScript继承IconScript

package com.android.launcher3;
 
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.text.format.Time;
import android.view.View;
import android.util.Log;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint;
import java.util.Calendar;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
 
public class WallpaperScript extends IconScript {  
    private float mDensity = 1.5f;  
    Time mTime = new Time();  
    int myCount =0;
    Context mContext; 
    Boolean isDraw =false;
     /** 
    * 效果展示目标View 
    */  
    private View mView; 
     /** 
    * 当前是否显示在屏幕上 
    */  
    private boolean mIsShowInScreen = false;  
       /** 
    * 通知系统更新视图现成 
    */  
    private WallpaperThread mWallpaperThread = null;  
    
    int[] arr=new int[]{R.drawable.ic_launcher_wallpaper_1,R.drawable.ic_launcher_wallpaper_2,R.drawable.ic_launcher_wallpaper_3,
                        R.drawable.ic_launcher_wallpaper_4,R.drawable.ic_launcher_wallpaper_5,R.drawable.ic_launcher_wallpaper_6
    };
    int index = 0;
    public WallpaperScript(Context context) {  
        super();  
        mContext = context;  
    }
    public void run(View view) {  
       mView = view;  
       if(mWallpaperThread == null){
           //Log.d("WallpaperScript","mWallpaperThread  ");        
           mWallpaperThread = new WallpaperThread();  
           mWallpaperThread.start();  
       }
         IntentFilter filter = new IntentFilter();  
         filter.addAction("android.intent.action.WallpaperChange");            
             view.getContext().registerReceiver(new BroadcastReceiver() {  
              @Override  
              public void onReceive(Context arg0, Intent arg1) {  
                   Log.d("WallpaperScript","onReceive  ");    
                   isDraw = true;
                   mWallpaperThread.startRun();  
                   mWallpaperThread.start();
                  // myCount =0;
              }  
         }, filter);         
    }  
     
   @Override  
   public void onPause() {  
       mWallpaperThread.pauseRun();  
       super.onPause();  
   }  
     
   @Override  
   public void onResume() {  
       mWallpaperThread.resumeRun();  
       super.onResume();  
   }  
     
   @Override  
   public void onStop() {  
       mWallpaperThread.stopRun();  
       super.onStop();  
   }  
  
    @Override  
    public void draw(Canvas canvas) {  
        super.draw(canvas);  
        
        Bitmap wallpaperIconfirst = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), arr[0]),mContext);  
        
        canvas.drawBitmap(wallpaperIconfirst, null, getBounds(),mPaint);//默认显示的图片 
        if(isDraw){
            
            index = index%6;
            
            Bitmap wallpaperIcon = Utilities.createIconBitmap( BitmapFactory.decodeResource(mContext.getResources(), arr[index]),mContext);  
            
            index = index 1;
            
        
            myCount =myCount 1;
            
            canvas.drawBitmap(wallpaperIcon, null, getBounds(),mPaint);//画底图  
        
       
            //Log.d("WallpaperScript","WallpaperScript index " index " myCount " myCount);
         
            if(myCount==49){
                myCount=0;
                mWallpaperThread.stopRun();
                //Log.d("WallpaperScript","WallpaperScript myCount "  myCount);
                isDraw = false;
            }    
            
        }
        
    }
      
    class WallpaperThread extends Thread {  
       int times = 0;  
       boolean running = true;  
 
       public boolean wait = false;  
       
        public void startRun() {  
           running = true;  
           synchronized (this) {  
               this.notify();  
           } 
       };  
 
       public void stopRun() {  
           running = false;  
           synchronized (this) {  
               this.notify();  
           } 
       };  
 
       public void pauseRun() {  
           /*this.wait = true;  
           synchronized (this) {  
               this.notify();  
           } */ 
       }  
 
       public void resumeRun() {  
           /*this.wait = false;  
           synchronized (this) {  
               this.notify();  
           }*/  
       }  
        
       public void run() { 
           Log.d("WallpaperScript","WallpaperThread running "  running);        
           while (running) {  
               synchronized (mView) {
                   Log.d("WallpaperScript","WallpaperThread run()");                   
                   mView.postInvalidate();  
               }  
               try {  
                   Thread.sleep(50);  
               } catch (Exception e) {  
                   System.out.println(e);  
               }  
                 
            
           }  
       }  
   }  
  
}  

把所有的图片放到一个数组里面,然后轮流去绘制里面的图片,点击图标的时候会发送一个广播,通过广播去控制线程的开启,这样功能基本上实现。

另外,怎样去实现没有界面的app,这个只需要AndroidManifest设置。

android:theme="@android:style/Theme.NoDisplay"

切换锁屏壁纸和主屏幕壁纸的代码

WallpaperManager manager = WallpaperManager.getInstance(this);
try {
    manager.setBitmap(bitmap,null, true, WallpaperManager.FLAG_LOCK | WallpaperManager.FLAG_SYSTEM);
} catch (Exception e) {
    e.printStackTrace();
}

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

android实现icon动态旋转效果的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  9. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

  10. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部