Cocos2d-x 3.x 头像选择器,本地相册与拍照+头像编辑功能(Android、IOS双平台实现)
来源:互联网 发布:苹果下载必备软件 编辑:程序博客网 时间:2024/05/18 17:41
大连游戏行业不是太发达,最后选择在一家应用外包公司工作,在工作和业余学习过程中积累了一点微不住道的经验,希望分享给热爱游戏的小伙伴们。
在应用开发过程中会常常有用户上传头像的功能,在网上找了N多资料发现没有人具体介绍过该用cocos2d-x实现。这篇文章就来介绍一下如何在Android和IOS平台上实现该功能。
先传一张完成后的图片一饱眼福:= = 怎么不好用呢~
直接上代码:
头文件 ImagePicker.h
/************************************************************************** * Copyright (c) 2015, pxbomb, All rights reserved. * File: ImagePicker.h * Date: 2015/06/02 18:02 * Author: 田伟汉 * Email: wilhan.tian@gmail.com * Depict: 图像选择器 **************************************************************************/#ifndef _IMAGEPICKER_H_#define _IMAGEPICKER_H_#include "cocos2d.h"#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include "platform/android/jni/JniHelper.h"#include <jni.h>#endif// CC_PLATFORM_ANDROID/** * 图像选择器 */class ImagePicker{public: // 获取选择器单例 static ImagePicker* getInstance(); // 销毁 static void destoryInstance();public: // 显示本地相册与相机选择器 void callImagePickerWithPhotoAndCamera(const std::function<void(std::string)>& callback); // 设置监听 void setListener(const std::function<void(std::string)>& callback); // 移除监听 void removeListener(); // 打开相册 void openPhoto(); // 打开相机 void openCamera(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) // 设置AppController void setViewController(void* viewController);#endif // CC_PLATFORM_IOSprotected: // 初始化 bool init(); ImagePicker(); protected: std::function<void(std::string)> m_callback; static ImagePicker* s_instance; #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) void* m_viewController;#endif // CC_PLATFORM_IOS };#endif // _IMAGEPICKER_H_
实现文件 ImagePicker.cpp
#include "ImagePicker.h"//--------------------------------------------------#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)#import "ImagePickerViewController.h"#import "RootViewController.h"#endif//--------------------------------------------------#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#define JAVA_CLASS "org/cocos2dx/cpp/ImagePicker"#define JAVA_FUNC_OPEN_PHOTO "openPhoto"#define JAVA_FUNC_OPEN_CAMERA "openCamera"#endif//--------------------------------------------------USING_NS_CC;//--------------------------------------------------ImagePicker* ImagePicker::s_instance = NULL;//--------------------------------------------------ImagePicker* ImagePicker::getInstance(){ if (s_instance == NULL) { s_instance = new ImagePicker(); } return s_instance;}//--------------------------------------------------void ImagePicker::destoryInstance(){ CC_SAFE_DELETE(s_instance);}//--------------------------------------------------ImagePicker::ImagePicker():m_callback(nullptr){ Director::getInstance()->getEventDispatcher()->addCustomEventListener("ImagePickerEvent", [=](EventCustom* eve) { std::string* path = (std::string*)eve->getUserData(); if (path && m_callback != nullptr) { m_callback(*path); } });}//--------------------------------------------------void ImagePicker::callImagePickerWithPhotoAndCamera(const std::function<void(std::string)>& callback){ s_instance->init(); setListener(callback);}//--------------------------------------------------void ImagePicker::setListener(const std::function<void(std::string)>& callback){ m_callback = callback;}//--------------------------------------------------void ImagePicker::removeListener(){ m_callback = nullptr;}//--------------------------------------------------void ImagePicker::openPhoto(){#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ImagePickerViewController* imagePickerViewController = [[ImagePickerViewController alloc] initWithNibName:nil bundle:nil]; RootViewController* _viewController = (RootViewController*)m_viewController; [_viewController.view addSubview:imagePickerViewController.view]; [imagePickerViewController localPhoto];#endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo info; bool ret = JniHelper::getStaticMethodInfo(info, JAVA_CLASS, JAVA_FUNC_OPEN_PHOTO,"()V"); if (ret) { info.env->CallStaticVoidMethod(info.classID, info.methodID); }#endif}//--------------------------------------------------void ImagePicker::openCamera(){#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ImagePickerViewController* imagePickerViewController = [[ImagePickerViewController alloc] initWithNibName:nil bundle:nil]; RootViewController* _viewController = (RootViewController*)m_viewController; [_viewController.view addSubview:imagePickerViewController.view]; [imagePickerViewController takePhoto];#endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo info; bool ret = JniHelper::getStaticMethodInfo(info, JAVA_CLASS, JAVA_FUNC_OPEN_CAMERA,"()V"); if (ret) { info.env->CallStaticVoidMethod(info.classID, info.methodID); }#endif}//--------------------------------------------------bool ImagePicker::init(){ cocos2d::Size visibleSize = Director::getInstance()->getVisibleSize(); //------------------------------------- // 根层 //------------------------------------- LayerColor* m_layer = LayerColor::create(Color4B(0, 0, 0, 125)); m_layer->retain(); //------------------------------------- // 按钮背景 //------------------------------------- Sprite* sprite = Sprite::create("ImagePicker/bk.png"); sprite->setAnchorPoint(Vec2(0.5, 0)); sprite->setPosition(Vec2(visibleSize.width/2, 0)); m_layer->addChild(sprite); //------------------------------------- // 按钮 //------------------------------------- Menu* menu = Menu::create(); menu->setPosition(Vec2::ZERO); m_layer->addChild(menu); //------------------------------------- MenuItemImage* btnPhoto = MenuItemImage::create("ImagePicker/ButtonPhoto.png", "ImagePicker/ButtonPhoto1.png", [=](Ref* p) { openPhoto(); }); btnPhoto->setAnchorPoint(Vec2(0.5, 1)); btnPhoto->setPosition(Vec2(visibleSize.width / 2, 280)); menu->addChild(btnPhoto); //------------------------------------- MenuItemImage* btnCamera = MenuItemImage::create("ImagePicker/ButtonCamera.png", "ImagePicker/ButtonCamera1.png", [=](Ref* p) { openCamera(); }); btnCamera->setAnchorPoint(Vec2(0.5, 1)); btnCamera->setPosition(btnPhoto->getPosition() + Vec2(0, -btnPhoto->getContentSize().height)); menu->addChild(btnCamera); //------------------------------------- MenuItemImage* btnCancel = MenuItemImage::create("ImagePicker/ButtonCancel.png", "ImagePicker/ButtonCancel1.png", [=](Ref* p) { float height = sprite->getContentSize().height; MoveBy* move = MoveBy::create(0.2, Vec2(0, -height)); sprite->runAction(move); menu ->runAction(move->clone()); Sequence* seq = Sequence::createWithTwoActions(FadeOut::create(0.2), RemoveSelf::create()); m_layer->runAction(seq); }); btnCancel->setAnchorPoint(Vec2(0.5, 1)); btnCancel->setPosition(btnCamera->getPosition() + Vec2(0, -btnCamera->getContentSize().height - 20)); menu->addChild(btnCancel); //------------------------------------- // 文字 //------------------------------------- Label* textPhoto = Label::createWithSystemFont("Photo", "", 24); textPhoto->setPosition(btnPhoto->getContentSize() / 2); textPhoto->setTextColor(Color4B::BLACK); btnPhoto->addChild(textPhoto); //------------------------------------- Label* textCamera = Label::createWithSystemFont("Camera", "", 24); textCamera->setPosition(btnPhoto->getContentSize() / 2); textCamera->setTextColor(Color4B::BLACK); btnCamera->addChild(textCamera); //------------------------------------- Label* textCancel = Label::createWithSystemFont("Cancel", "", 24); textCancel->setPosition(btnPhoto->getContentSize() / 2); textCancel->setTextColor(Color4B::BLACK); btnCancel->addChild(textCancel); //------------------------------------- // 准备显示 //------------------------------------- Director::getInstance()->getRunningScene()->scheduleOnce([=](float time) { Director::getInstance()->getRunningScene()->addChild(m_layer, INT_MAX); m_layer->release(); float height = sprite->getContentSize().height; sprite->setPositionY(sprite->getPositionY() - height); menu ->setPositionY(menu->getPositionY() - height); MoveBy* move = MoveBy::create(0.3, Vec2(0, height)); sprite->runAction(move); menu ->runAction(move->clone()); m_layer->setOpacity(0); m_layer->runAction(FadeTo::create(0.2, 125)); }, 0.1, "ImagePickerScheduleOnce"); //------------------------------------- // 截断事件 //------------------------------------- EventListenerTouchOneByOne* touchEvent = EventListenerTouchOneByOne::create(); touchEvent->setSwallowTouches(true); touchEvent->onTouchBegan = [=](Touch* touch, Event* eve) { if(sprite->getBoundingBox().containsPoint(touch->getLocation())) return true; float height = sprite->getContentSize().height; MoveBy* move = MoveBy::create(0.2, Vec2(0, -height)); sprite->runAction(move); menu ->runAction(move->clone()); Sequence* seq = Sequence::createWithTwoActions(FadeOut::create(0.2), RemoveSelf::create()); m_layer->runAction(seq); return true; }; Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchEvent, sprite); //------------------------------------- return true;}//--------------------------------------------------#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)void ImagePicker::setViewController(void* viewController){ m_viewController = viewController;}#endif//--------------------------------------------------#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)extern "C"{ void Java_org_cocos2dx_cpp_ImagePicker_onImageSaved(JNIEnv* env, jobject thiz, jstring path) { std::string strPath = JniHelper::jstring2string(path); Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("ImagePickerEvent", &strPath); }}#endif//--------------------------------------------------
为工程添加资源:略
(图片资源和代码下载地址:点击打开链接)
分平台实现:
------------------------------------------
Android
------------------------------------------
1. 打开Eclipse在org.cocos2x.cpp(加入你没改过的话)包名下新建“ImagePicker.java”文件
ImagePicker.java具体代码如下:
public class ImagePicker{<span style="white-space:pre"></span>public static final int NONE = 0; public static final int PHOTOHRAPH = 1;// 拍照 public static final int PHOTOZOOM = 2; // 缩放 public static final int PHOTORESOULT = 3;// 结果 public static final String IMAGE_UNSPECIFIED = "image/*"; private static ImagePicker instance = null; private static Activity activity = null; public static native void onImageSaved(String path); public static ImagePicker getInstance(){ if(instance == null){ instance = new ImagePicker(); } return instance; } // 初始化 public void init(Activity activity){ ImagePicker.activity = activity; } // 打开相册static public void openPhoto(){Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED); activity.startActivityForResult(intent, PHOTOZOOM);} // 打开相机static public void openCamera(){ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(activity.getFilesDir(), "@cc_cameraCache.jpg"))); activity.startActivityForResult(intent, PHOTOHRAPH); }// 回调public void onActivityResult(int requestCode, int resultCode, Intent data){if (resultCode == NONE) return; // 拍照 if (requestCode == PHOTOHRAPH) { File picture = new File(activity.getFilesDir() + "/@cc_cameraCache.jpg"); startPhotoZoom(Uri.fromFile(picture)); } if (data == null) return; // 读取相册缩放图片 if (requestCode == PHOTOZOOM) { startPhotoZoom(data.getData()); } // 处理结果 if (requestCode == PHOTORESOULT) { Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); ByteArrayOutputStream stream = new ByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.JPEG, 75, stream); // XXX/@ci_8888-8888-8888-8888.jpg String path = activity.getFilesDir() + "/@ci_" + UUID.randomUUID().toString() + ".jpg"; saveMyBitmap(path, photo); // 通知C++层已保存图片 并返回路径 onImageSaved(path); } }}public void startPhotoZoom(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, IMAGE_UNSPECIFIED); intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 100); intent.putExtra("outputY", 100); intent.putExtra("return-data", true); activity.startActivityForResult(intent, PHOTORESOULT); }public void saveMyBitmap(String filePath, Bitmap mBitmap){ File f = new File(filePath); try { f.createNewFile(); } catch (IOException e) { } FileOutputStream fOut = null; try { fOut = new FileOutputStream(f); } catch (FileNotFoundException e) { e.printStackTrace(); } mBitmap.compress(Bitmap.CompressFormat.JPEG, 70, fOut); try { fOut.flush(); } catch (IOException e) { e.printStackTrace(); } try { fOut.close(); } catch (IOException e) { e.printStackTrace(); } }}
2. 在Android入口进行初始化
打开AppActivity.java文件,复写OnCreate()与onActivityResult()方法。
在OnCreate方法中对我们的类初始化:“ImagePicker.getInstance().init(this);”
在onActivityResult()中将回调参数传递到ImagePicker中:“ImagePicker.getInstance().onActivityResult(requestCode, resultCode, data);”
AppActivity.java具体代码:
public class AppActivity extends Cocos2dxActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);ImagePicker.getInstance().init(this);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);ImagePicker.getInstance().onActivityResult(requestCode, resultCode, data);}}
3. 最后在AndroidManifest.xml加入访问相机权限"<uses-permission android:name="android.permission.CAMERA"/>"
------------------------------------------
IOS
------------------------------------------
1. 将开始创建的ImagePicker.cpp文件后缀名改为.mm文件。
2. 在proj.ioc_mac/ios文件夹下创建两个文件,分别为ImagePickerViewController.h、ImagePickerViewController.mm
ImagePickerViewController.h具体代码:
#import <UIKit/UIKit.h>@interface ImagePickerViewController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>{ NSString* filePath;}// 打开本地相册- (void)localPhoto;// 打开相机- (void)takePhoto;@end
ImagePickerViewController.mm具体代码:
#import "ImagePickerViewController.h"#import "cocos2d.h"@interface ImagePickerViewController ()@end@implementation ImagePickerViewController- (void)viewDidLoad { [super viewDidLoad]; //[self localPhoto];}- (void)viewDidUnload{ [super viewDidUnload];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}-(void)localPhoto{ UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; picker.allowsEditing = YES; //[self presentModalViewController:picker animated:YES]; [self presentViewController:picker animated:YES completion:^(void){ NSLog(@"Imageviewcontroller is presented"); }]; [picker release]; NSLog(@"-(void)localPhoto();");}- (void)takePhoto{ UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController* picker = [[UIImagePickerController alloc] init]; picker.delegate = self; //设置拍照后的图像可编辑 picker.allowsEditing = YES; picker.sourceType = sourceType; [picker release]; [self presentModalViewController:picker animated:YES]; } else{ NSLog(@"模拟器中无法打开照相机,请在真机中调试"); }}- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; //当选择的类型是图片 if ([type isEqualToString:@"public.image"]) { //先把图片转成NSData// UIImage* image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; UIImage* image = [info objectForKey:@"UIImagePickerControllerEditedImage"]; NSData *data; if (UIImagePNGRepresentation(image) == nil) { data = UIImageJPEGRepresentation(image, 1.0); } else { data = UIImagePNGRepresentation(image); } //图片保存的路径 //这里将图片放在沙盒的documents文件夹中 NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; //文件管理器 NSFileManager *fileManager = [NSFileManager defaultManager]; //生成唯一字符串 NSString* uuid = [[NSUUID UUID] UUIDString]; //文件名 NSString* fileName = [NSString stringWithFormat:@"/%@.png", uuid]; //把刚刚图片转换的data对象拷贝至沙盒中 并保存为XXXXXXXX-XXXX-XXXX....XXXX.png [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil]; [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:fileName] contents:data attributes:nil]; //得到选择后沙盒中图片的完整路径 filePath = [[NSString alloc]initWithFormat:@"%@%@", DocumentsPath, fileName]; //关闭相册界面 [picker dismissModalViewControllerAnimated:YES]; std::string strFilePath = [filePath UTF8String]; cocos2d::Director::getInstance()->getEventDispatcher()->dispatchCustomEvent("ImagePickerEvent", &strFilePath); } }- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ NSLog(@"您取消了选择图片"); [picker dismissModalViewControllerAnimated:YES];}@end
3. 修改原工程AppController.mm文件,加入一行“ImagePicker::getInstance()->setViewController(_viewController);”用来初始化。
AppController.mm具体代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { cocos2d::Application *app = cocos2d::Application::getInstance(); app->initGLContextAttrs(); cocos2d::GLViewImpl::convertAttrs(); // Override point for customization after application launch. // Add the view controller's view to the window and display. window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; // Init the CCEAGLView CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds] pixelFormat: (NSString*)cocos2d::GLViewImpl::_pixelFormat depthFormat: cocos2d::GLViewImpl::_depthFormat preserveBackbuffer: NO sharegroup: nil multiSampling: NO numberOfSamples: 0 ]; // Use RootViewController manage CCEAGLView _viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil]; _viewController.wantsFullScreenLayout = YES; _viewController.view = eaglView; //---------------------------------- // 初始化ImagePicker //---------------------------------- ImagePicker::getInstance()->setViewController(_viewController); //---------------------------------- // Set RootViewController to window if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0) { // warning: addSubView doesn't work on iOS6 [window addSubview: _viewController.view]; } else { // use this method on ios6 [window setRootViewController:_viewController]; } [window makeKeyAndVisible]; [[UIApplication sharedApplication] setStatusBarHidden:true]; // IMPORTANT: Setting the GLView should be done after creating the RootViewController cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView(eaglView); cocos2d::Director::getInstance()->setOpenGLView(glview); app->run(); return YES;}
ImagePicker::getInstance()->callImagePickerWithPhotoAndCamera([=](std::string path) { //做你想做的事情 });忘了说明,参数path就是你已经选择并编辑后,图片的真实路径。
咳咳,请各位大神轻喷,喜欢游戏的程序孩纸伤不起~不说了,回家LOL去了~
- Cocos2d-x 3.x 头像选择器,本地相册与拍照+头像编辑功能(Android、IOS双平台实现)
- quick cocos2d-x 与android实现更换头像
- Android 相册和拍照设置头像功能
- cocos2d-x与安卓混编实现“更换头像”
- Android 头像(拍照,相册)选择后裁剪功能
- Android设置头像,手机拍照或从本地相册选取图片作为头像
- Android设置头像,手机拍照或从本地相册选取图片作为头像
- Android设置头像,手机拍照或从本地相册选取图片作为头像
- Android设置头像,手机拍照或从本地相册选取图片作为头像
- Android调用系统相册或拍照实现头像更换
- 上传头像 拍照 相册
- android头像选择(拍照,相册,裁剪)
- android头像选择(拍照,相册,裁剪)
- Android 上传头像的拍照跟相册
- Android打开系统拍照&相册获取头像
- Android 拍照或从相册设置头像
- 【学习ios之路:UI系列】点击更换头像实现从相册读取照片和拍照两种功能
- android:拍照/本地上传头像+本地缓存
- SpringMVC笔记
- 砸金花变牌高科技╯★【在线演示QQ:194714506】
- 单链表的拆分 SDUT -2120
- 砸金花变牌视频ξ▆【在线演示QQ:194714506】
- 三公作弊高科技》Ψ【在线演示QQ:194714506】
- Cocos2d-x 3.x 头像选择器,本地相册与拍照+头像编辑功能(Android、IOS双平台实现)
- 三公变牌高科技╭↙【在线演示QQ:194714506】
- 使用JQuery数据模板Handlerbars
- 三公变牌视频ㄨ▆【在线演示QQ:194714506】
- 普通扑克作弊高科技█◥【在线演示QQ:194714506】
- 一些有意思的网页
- 普通扑克变牌高科技㊣◤【在线演示QQ:194714506】
- 黑马程序员_java语言_多线程
- 普通扑克变牌视频△←【在线演示QQ:194714506】