Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)

Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)

 2013/10/19 17:47:32  安卓吧  博客园  我要评论(0)
  • 摘要:源码:http://files.cnblogs.com/android100/StandardCamera2013-10-18.zip废话不说了,就是加个seekbar,拖动的话能够调节焦距,让画面变大或缩小。下面是核心程序:一,camera的布局文件<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android
  • 标签:android 下载 代码 开发 摄像头

源码:http://files.cnblogs.com/android100/StandardCamera2013-10-18.zip

废话不说了,就是加个seekbar,拖动的话能够调节焦距,让画面变大或缩小。下面是核心程序:

一,camera的布局文件

    class="dp-xml">
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/BestWish"  
  11.         tools:context=".StandardCamera" />  
  12.   
  13.     <RelativeLayout  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content" >  
  16.   
  17.         <FrameLayout  
  18.             android:layout_width="wrap_content"  
  19.             android:layout_height="wrap_content" >  
  20.   
  21.             <SurfaceView  
  22.                 android:id="@+id/previewSV"  
  23.                 android:layout_width="fill_parent"  
  24.                 android:layout_height="wrap_content" />  
  25.         </FrameLayout>  
  26.           
  27.         <LinearLayout  
  28.         android:id="@+id/zoomLayout"  
  29.         android:layout_width="wrap_content"  
  30.         android:layout_height="40dp"  
  31.         android:layout_centerInParent="true"  
  32.         android:layout_centerHorizontal="true"                  
  33.         android:orientation="horizontal" >  
  34.   
  35.         <TextView  
  36.             android:id="@+id/textView1"  
  37.             android:layout_width="wrap_content"  
  38.             android:layout_height="wrap_content"  
  39.             android:text="-"  
  40.             android:textColor="#ffffff"   
  41.             android:textSize="30dip"/>  
  42.   
  43.         <SeekBar  
  44.             android:id="@+id/seekbar_zoom"  
  45.             android:layout_width="300dp"  
  46.             android:layout_height="wrap_content"  
  47.             android:layout_gravity="center_vertical"  
  48.            android:progressDrawable="@drawable/seekbar_style"  
  49.             android:thumb="@drawable/ic_launcher"  
  50.             android:thumbOffset="0dp" />  
  51.   
  52.         <TextView  
  53.             android:id="@+id/textView2"  
  54.             android:layout_width="wrap_content"  
  55.             android:layout_height="wrap_content"  
  56.              android:text="+"  
  57.             android:textColor="#ffffff"  
  58.             android:textSize="30dip" />  
  59.     </LinearLayout>  
  60.     </RelativeLayout>  
  61.   
  62.       
  63.   
  64.     <ImageButton  
  65.         android:id="@+id/photoImgBtn"  
  66.         android:layout_width="wrap_content"  
  67.         android:layout_height="wrap_content"  
  68.         android:layout_gravity="center"  
  69.         android:background="@drawable/photo_img_btn" />  
  70.   
  71. </LinearLayout>  


其中里面嵌套的LinearLayout就是那个ZoomBar,最外面我用了相对布局,发现相对布局用起来还是很好用的。为了方便以后扩展,Camera的SurfaceView用的帧布局。注意SeekBar的几个参数,其中的progressDrawable是指那个横条的形状,可以直接用个图片,也可以写个xml文件。这里用的是xml,当然用图片很简单。seekbar_style.xml文件如下:

  1. <?xml version="1.0" encoding="UTF-8"?>     
  2. <layer-list xmlns:android="http://schemas.android.com/apk/res/android">     
  3.   <item android:id="@android:id/background">    
  4.          <shape>    
  5.              <corners android:radius="5dip" />    
  6.              <gradient    
  7.                      android:startColor="#ff9d9e9d"    
  8.                      android:centerColor="#ff5a5d5a"    
  9.                      android:centerY="0.75"    
  10.                      android:endColor="#ff747674"    
  11.                      android:angle="270"    
  12.              />    
  13.          </shape>    
  14.      </item>    
  15. </layer-list>     


下面的android:thumb是滑动的那个手柄,本来我是写了一个xml文件,名字为thumb.xml如下:

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.   
  4.     <!-- 按下状态 -->  
  5.     <item android:state_focused="true" android:state_pressed="true"><shape android:shape="oval">  
  6.             <gradient android:angle="0" android:centerColor="#FF00FF00" android:endColor="#000000" android:gradientRadius="8" android:startColor="#FFFF0000" android:type="radial" />  
  7.   
  8.             <size android:height="20dip" android:width="20dip"></size>  
  9.         </shape></item>  
  10.   
  11.   
  12. </selector>  

无奈啥也显示不出来,索性直接找了个粗糙的图片,见谅哈!

二,整个程序的主代码:

  1. package yan.guoqi.camera;  
  2. import java.io.BufferedOutputStream;  
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.util.List;  
  7.   
  8. import yan.guoqi.rectphoto.R;  
  9. import android.app.Activity;  
  10. import android.content.Context;  
  11. import android.graphics.Bitmap;  
  12. import android.graphics.BitmapFactory;  
  13. import android.graphics.ColorMatrixColorFilter;  
  14. import android.graphics.Matrix;  
  15. import android.graphics.PixelFormat;  
  16. import android.hardware.Camera;  
  17. import android.hardware.Camera.AutoFocusCallback;  
  18. import android.hardware.Camera.Parameters;  
  19. import android.hardware.Camera.PictureCallback;  
  20. import android.hardware.Camera.PreviewCallback;  
  21. import android.hardware.Camera.ShutterCallback;  
  22. import android.os.Bundle;  
  23. import android.util.Log;  
  24. import android.view.Display;  
  25. import android.view.MotionEvent;  
  26. import android.view.SurfaceHolder;  
  27. import android.view.SurfaceView;  
  28. import android.view.View;  
  29. import android.view.View.OnClickListener;  
  30. import android.view.View.OnTouchListener;  
  31. import android.view.ViewGroup.LayoutParams;  
  32. import android.view.Window;  
  33. import android.view.WindowManager;  
  34. import android.widget.ImageButton;  
  35. import android.widget.SeekBar;  
  36. import android.widget.SeekBar.OnSeekBarChangeListener;  
  37.   
  38. public class StandardCamera extends Activity implements SurfaceHolder.Callback, PreviewCallback{  
  39.     private static final String tag="StandardCamera";  
  40.     private boolean isPreview = false;  
  41.     private SurfaceView mPreviewSV = null//棰勮SurfaceView  
  42.     private SurfaceHolder mySurfaceHolder = null;  
  43.     private ImageButton mPhotoImgBtn = null;  
  44.     private Camera myCamera = null;  
  45.     private Bitmap mBitmap = null;  
  46.     private AutoFocusCallback myAutoFocusCallback = null;  
  47.     boolean flag = true;  
  48.       
  49.     private SeekBar mZoomBar = null;  
  50.   
  51.     @Override  
  52.     public void onCreate(Bundle savedInstanceState) {  
  53.         super.onCreate(savedInstanceState);  
  54.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  55.         int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;  
  56.         Window myWindow = this.getWindow();  
  57.         myWindow.setFlags(flag, flag);  
  58.   
  59.         setContentView(R.layout.activity_rect_photo);  
  60.   
  61.         initView();  
  62.         mySurfaceHolder = mPreviewSV.getHolder();  
  63.         mySurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);  
  64.         mySurfaceHolder.addCallback(this);  
  65.         mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  66.   
  67.   
  68.         myAutoFocusCallback = new AutoFocusCallback() {  
  69.   
  70.             public void onAutoFocus(boolean success, Camera camera) {  
  71.                 // TODO Auto-generated method stub  
  72.                 if(success)  
  73.                 {  
  74.                     Log.i(tag, "myAutoFocusCallback: success...");  
  75.   
  76.   
  77.                 }  
  78.                 else  
  79.                 {  
  80.                     Log.i(tag, "myAutoFocusCallback: 澶辫触浜??.");  
  81.   
  82.                 }  
  83.   
  84.   
  85.             }  
  86.         };  
  87.           
  88.         //添加ZoomBar  
  89.         mZoomBar = (SeekBar)findViewById(R.id.seekbar_zoom);  
  90.         mZoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {  
  91.               
  92.             public void onStopTrackingTouch(SeekBar seekBar) {  
  93.                 // TODO Auto-generated method stub  
  94.                   
  95.             }  
  96.               
  97.             public void onStartTrackingTouch(SeekBar seekBar) {  
  98.                 // TODO Auto-generated method stub  
  99.                   
  100.             }  
  101.               
  102.             public void onProgressChanged(SeekBar seekBar, int progress,  
  103.                     boolean fromUser) {  
  104.                 // TODO Auto-generated method stub  
  105.                 Parameters p = myCamera.getParameters();  
  106.                 p.setZoom(progress);  
  107.                 myCamera.setParameters(p);  
  108.             }  
  109.         });  
  110.   
  111.   
  112.   
  113.     }  
  114.   
  115.     public void initView(){  
  116.         mPreviewSV = (SurfaceView)findViewById(R.id.previewSV);  
  117.         WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);  
  118.         Display display = wm.getDefaultDisplay();  
  119.         LayoutParams lpSV = mPreviewSV.getLayoutParams();  
  120.         lpSV.width = display.getWidth();  
  121.         lpSV.height = (int) ((float)display.getHeight()*0.75);  
  122.         mPreviewSV.setLayoutParams(lpSV);  
  123.   
  124.   
  125.             mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);  
  126.         LayoutParams lp = mPhotoImgBtn.getLayoutParams();  
  127.         lp.width = 240;  
  128.         lp.height = 240;          
  129.         mPhotoImgBtn.setLayoutParams(lp);                 
  130.         mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());  
  131.         mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());  
  132.     }  
  133.   
  134.     public void surfaceChanged(SurfaceHolder holder, int format, int width,int height)   
  135.     {  
  136.         // TODO Auto-generated method stub        
  137.         Log.i(tag, "SurfaceHolder.Callback:surfaceChanged!");  
  138.         initCamera();  
  139.   
  140.     }  
  141.   
  142.   
  143.     public void surfaceCreated(SurfaceHolder holder)   
  144.     {  
  145.         // TODO Auto-generated method stub        
  146.         myCamera = Camera.open();  
  147.         try {  
  148.             myCamera.setPreviewDisplay(mySurfaceHolder);  
  149.             Log.i(tag, "SurfaceHolder.Callback: surfaceCreated!");  
  150.         } catch (IOException e) {  
  151.             // TODO Auto-generated catch block  
  152.             if(null != myCamera){  
  153.                 myCamera.release();  
  154.                 myCamera = null;  
  155.             }  
  156.             e.printStackTrace();  
  157.         }  
  158.   
  159.   
  160.   
  161.     }  
  162.   
  163.   
  164.     public void surfaceDestroyed(SurfaceHolder holder)   
  165.   
  166.     {  
  167.         // TODO Auto-generated method stub  
  168.         Log.i(tag, "SurfaceHolder.Callback锛歋urface Destroyed");  
  169.         if(null != myCamera)  
  170.         {  
  171.             myCamera.setPreviewCallback(null);   
  172.   
  173.             myCamera.stopPreview();   
  174.             isPreview = false;   
  175.             myCamera.release();  
  176.             myCamera = null;       
  177.         }  
  178.   
  179.     }  
  180.   
  181.     public void initCamera(){  
  182.         if(isPreview){  
  183.             myCamera.stopPreview();  
  184.         }  
  185.         if(null != myCamera){             
  186.             Camera.Parameters myParam = myCamera.getParameters();  
  187.   
  188.   
  189.             myParam.setPictureFormat(PixelFormat.JPEG);//璁剧疆鎷嶇収鍚庡瓨鍌ㄧ殑鍥剧墖鏍煎紡  
  190.   
  191.               
  192.             //List<Size> pictureSizes = myParam.getSupportedPictureSizes();  
  193.                         //List<Size> previewSizes = myParam.getSupportedPreviewSizes();  
  194.             //          for(int i=0; i<pictureSizes.size(); i++){  
  195.             //              Size size = pictureSizes.get(i);  
  196.             //              Log.i(tag, "initCamera:pictureSizes: width = "+size.width+"height = "+size.height);  
  197.             //          }  
  198.             //          for(int i=0; i<previewSizes.size(); i++){  
  199.             //              Size size = previewSizes.get(i);  
  200.             //              Log.i(tag, "initCamera:鎽勫儚澶存敮鎸佺殑previewSizes: width = "+size.width+"height = "+size.height);  
  201.             //  
  202.             //          }  
  203.   
  204.   
  205.   
  206.             myParam.setPictureSize(1280960);  //  
  207.             myParam.setPreviewSize(960720);   //        
  208.             //myParam.set("rotation", 90);                
  209.             myCamera.setDisplayOrientation(90);    
  210.             List<String> focuseMode = (myParam.getSupportedFocusModes());  
  211.             for(int i=0; i<focuseMode.size(); i++){  
  212.                 Log.i(tag, focuseMode.get(i));  
  213.                 if(focuseMode.get(i).contains("continuous")){  
  214.                     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);  
  215.                 }  
  216.                 else{  
  217.                     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);  
  218.   
  219.                 }  
  220.             }  
  221.             //设置mZoomBar的最大值  
  222.             mZoomBar.setMax(myParam.getMaxZoom());  
  223.             myCamera.setParameters(myParam);              
  224.             myCamera.startPreview();  
  225.             myCamera.autoFocus(myAutoFocusCallback);  
  226.             isPreview = true;  
  227.         }  
  228.     }  
  229.   
  230.     ShutterCallback myShutterCallback = new ShutterCallback()   
  231.     {  
  232.   
  233.         public void onShutter() {  
  234.             // TODO Auto-generated method stub  
  235.             Log.i(tag, "myShutterCallback:onShutter...");  
  236.   
  237.         }  
  238.     };  
  239.     PictureCallback myRawCallback = new PictureCallback()   
  240.     {  
  241.   
  242.         public void onPictureTaken(byte[] data, Camera camera) {  
  243.             // TODO Auto-generated method stub  
  244.             Log.i(tag, "myRawCallback:onPictureTaken...");  
  245.   
  246.         }  
  247.     };  
  248.     PictureCallback myJpegCallback = new PictureCallback()   
  249.     {  
  250.   
  251.         public void onPictureTaken(byte[] data, Camera camera) {  
  252.             // TODO Auto-generated method stub  
  253.             Log.i(tag, "myJpegCallback:onPictureTaken...");  
  254.             if(null != data){  
  255.                 mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data鏄瓧鑺傛暟鎹紝灏嗗叾瑙f瀽鎴愪綅鍥?                myCamera.stopPreview();  
  256.                 isPreview = false;  
  257.             }  
  258.             Matrix matrix = new Matrix();  
  259.             matrix.postRotate((float)90.0);  
  260.             Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 00, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);  
  261.             if(null != rotaBitmap)  
  262.             {  
  263.                 saveJpeg(rotaBitmap);  
  264.             }  
  265.   
  266.             myCamera.startPreview();  
  267.             isPreview = true;  
  268.         }  
  269.     };  
  270.     public class PhotoOnClickListener implements OnClickListener{  
  271.   
  272.         public void onClick(View v) {  
  273.             // TODO Auto-generated method stub  
  274.             if(isPreview && myCamera!=null){  
  275.                 myCamera.takePicture(myShutterCallback, null, myJpegCallback);    
  276.             }  
  277.   
  278.         }  
  279.   
  280.     }  
  281.   
  282.     public void saveJpeg(Bitmap bm){  
  283.         String savePath = "/mnt/sdcard/rectPhoto/";  
  284.         File folder = new File(savePath);  
  285.         if(!folder.exists()) {  
  286.             folder.mkdir();  
  287.         }  
  288.         long dataTake = System.currentTimeMillis();  
  289.         String jpegName = savePath + dataTake +".jpg";  
  290.         Log.i(tag, "saveJpeg:jpegName--" + jpegName);  
  291.         //File jpegFile = new File(jpegName);  
  292.         try {  
  293.             FileOutputStream fout = new FileOutputStream(jpegName);  
  294.             BufferedOutputStream bos = new BufferedOutputStream(fout);  
  295.   
  296.             //          Bitmap newBM = bm.createScaledBitmap(bm, 600, 800, false);  
  297.   
  298.             bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
  299.             bos.flush();  
  300.             bos.close();  
  301.         } catch (IOException e) {  
  302.             // TODO Auto-generated catch block  
  303.   
  304.             e.printStackTrace();  
  305.         }  
  306.     }  
  307.   
  308.   
  309.     public class MyOnTouchListener implements OnTouchListener{  
  310.   
  311.         public final  float[] BT_SELECTED=new float[]  
  312.                 { 20002,  
  313.                 02002,  
  314.                 00202,  
  315.                 00010 };                  
  316.   
  317.         public final float[] BT_NOT_SELECTED=new float[]  
  318.                 { 10000,  
  319.                 01000,  
  320.                 00100,  
  321.                 00010 };  
  322.         public boolean onTouch(View v, MotionEvent event) {  
  323.             // TODO Auto-generated method stub  
  324.             if(event.getAction() == MotionEvent.ACTION_DOWN){  
  325.                 v.getBackground().setColorFilter(new ColorMatrixColorFilter(BT_SELECTED));  
  326.                 v.setBackgroundDrawable(v.getBackground());  
  327.             }  
  328.             else if(event.getAction() == MotionEvent.ACTION_UP){  
  329.                 v.getBackground().setColorFilter(new ColorMatrixColorFilter(BT_NOT_SELECTED));  
  330.                 v.setBackgroundDrawable(v.getBackground());  
  331.   
  332.             }  
  333.             return false;  
  334.         }  
  335.   
  336.     }  
  337.   
  338.     @Override  
  339.     public void onBackPressed()  
  340.     {  
  341.         // TODO Auto-generated method stub  
  342.         super.onBackPressed();  
  343.         StandardCamera.this.finish();  
  344.     }  
  345.   
  346.   
  347.   
  348.     class UpdateThread implements Runnable{  
  349.   
  350.         public void run() {  
  351.             // TODO Auto-generated method stub  
  352.             while(flag){  
  353.                 if(myCamera!=null && isPreview)  
  354.                     myCamera.autoFocus(myAutoFocusCallback); //鑷姩鑱氱劍  
  355.                 myCamera.setOneShotPreviewCallback(StandardCamera.this); //onPreviewFrame閲屼細鎺ュ彈鍒版暟鎹??           myCamera.stopPreview(); //鍋滄棰勮  
  356.                 flag = false;  
  357.   
  358.                 try {  
  359.                     Thread.sleep(1000);  
  360.                 } catch (InterruptedException e) {  
  361.                     // TODO Auto-generated catch block  
  362.                     e.printStackTrace();  
  363.                 }  
  364.             }  
  365.         }  
  366.   
  367.     }  
  368.   
  369.   
  370.   
  371.     public void onPreviewFrame(byte[] data, Camera camera) {  
  372.         // TODO Auto-generated method stub  
  373.   
  374.     }  
  375. }  

需要注意的有以下几点:

1,为了让程序适用不同的手机,onCreate函数里用如下代码初始化SurfaceView的大小,避免以前写死的方法:

 public void initView(){
  mPreviewSV = (SurfaceView)findViewById(R.id.previewSV);
  WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
  Display display = wm.getDefaultDisplay();
        LayoutParams lpSV = mPreviewSV.getLayoutParams();
        lpSV.width = display.getWidth();
        lpSV.height = (int) ((float)display.getHeight()*0.75);
        mPreviewSV.setLayoutParams(lpSV);

   mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
  LayoutParams lp = mPhotoImgBtn.getLayoutParams();
  lp.width = 240;
  lp.height = 240;  
  mPhotoImgBtn.setLayoutParams(lp);    
  mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
  mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
 }

2,关于ZoomBar的代码片段很简短,如下:


   mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
  LayoutParams lp = mPhotoImgBtn.getLayoutParams();
  lp.width = 240;
  lp.height = 240;  
  mPhotoImgBtn.setLayoutParams(lp);    
  mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
  mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
 }
  //添加ZoomBar
  mZoomBar = (SeekBar)findViewById(R.id.seekbar_zoom);
  mZoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
   
   public void onStopTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
   }
   
   public void onStartTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
   }
   
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    // TODO Auto-generated method stub
    Parameters p = myCamera.getParameters();
    p.setZoom(progress);
    myCamera.setParameters(p);
   }
  });

3,在initCamera函数里,查询camera支持的聚焦模式,如果带连续视频聚焦则使用连续视频聚焦,否则使用自动聚焦:


   mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
  LayoutParams lp = mPhotoImgBtn.getLayoutParams();
  lp.width = 240;
  lp.height = 240;  
  mPhotoImgBtn.setLayoutParams(lp);    
  mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
  mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
 }
List<String> focuseMode = (myParam.getSupportedFocusModes());
   for(int i=0; i<focuseMode.size(); i++){
    Log.i(tag, focuseMode.get(i));
    if(focuseMode.get(i).contains("continuous")){
     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
    }
    else{
     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    }
   }

4,同样在initCamera函数里,设置ZoomBar的最大值:
//设置mZoomBar的最大值
   mZoomBar.setMax(myParam.getMaxZoom());

后续将写专文分析Camera4.0的源码,并且模仿到自己的代码中!

上一篇: Mac OSX 快捷键&命令行 下一篇: 没有下一篇了!
  • 相关文章
发表评论
用户名: 匿名