在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
cocos2d-x官方自带的输入框,简直惨不忍睹,在ios还好,在安卓简直了。。用过的都知道。。。 所以为了用户体验,我们自己搞一个吧。输入框这种东西比较特殊,不像按钮、列表框之类的很容易实现,因为涉及到复制粘贴、操作虚拟键盘等,所以当然是用安卓原生的输入框最好了。 非常感谢我们的主程陈剑大哥,思路是陈剑大哥想的,我只负责记录一下。 本来代码50天前就写好了,但是绑定到js一直失败,恶心了好几天放弃了。前几天在用lua写点东西,把之前的代码拷过来试着绑定到lua,结果一次就成功了,完全没有踩坑,不知道说什么好了。。而且前几天官方发布了cocos2d-x 3.8版本,已经自带了,所以现在再发出来感觉毫无竞争力了呢。。。 使用原生控件的优点不用多说了,缺点当然也是有的。例如排版、布局、屏幕适配等,都要适应cocos2d的规则,而且由于是系统控件,渲染层级不受cocos2d的zorder的影响。当然这些努力一下也是可以解决的。 要注意的有: 1、c++通过jni控制java创建安卓控件。 2、c++持有java对象的引用,防止垃圾回收。 3、java回调c语言,c语言调用c++,所以需要处理好java对象与c++对象的对应关系。 我的做法是: 1、创建一个输入框工厂类,负责根据不同平台生成输入框,当然我只会安卓的。 2、工厂类维护一个map,保存c++对象和java对象的对应关系。 3、根据cocos2d的世界坐标系,更新安卓原生控件。
防止恶意转载还改名的恶心行为。本博客地址:http://www.cnblogs.com/wolfred7464/ 上代码吧: 1 #ifndef __CocosAndroidStudio__EditText__ 2 #define __CocosAndroidStudio__EditText__ 3 4 #include <string> 5 #include "cocos2d.h" 6 7 class EditText : public cocos2d::Node { 8 public: 9 virtual ~EditText() {}; 10 virtual void setString(const std::string& str) = 0; 11 virtual std::string getString() = 0; 12 13 protected: 14 15 16 }; 17 18 #endif /* defined(__CocosAndroidStudio__EditText__) */ 1 #ifndef __CocosAndroidStudio__EditTextAndroid__ 2 #define __CocosAndroidStudio__EditTextAndroid__ 3 4 #include "EditText.h" 5 #include "platform/android/jni/JniHelper.h" 6 #include "EditTextFactory.h" 7 8 class EditTextAndroid : public EditText { 9 public: 10 ~EditTextAndroid(); 11 12 virtual void setString(const std::string& str) override; 13 virtual std::string getString() override; 14 15 virtual void setPosition(const cocos2d::Vec2& pos) override; 16 virtual void setContentSize(const cocos2d::Size& size) override; 17 18 virtual void onEnter() override; 19 20 friend class EditTextFactory; 21 22 private: 23 EditTextAndroid(); 24 static EditTextAndroid* create(); 25 26 cocos2d::JniMethodInfo getJavaMethod(const char* name, const char* param); 27 void setPositionAndroid(); 28 void setContentSizeAndroid(); 29 30 jobject _object; 31 }; 32 33 #endif /* defined(__CocosAndroidStudio__EditTextAndroid__) */ 1 #include "EditTextAndroid.h" 2 #include "cocos2d.h" 3 #include <unistd.h> 4 #include <string> 5 6 USING_NS_CC; 7 using namespace std; 8 9 EditTextAndroid* EditTextAndroid::create() { 10 auto ret = new EditTextAndroid(); 11 ret->autorelease(); 12 return ret; 13 } 14 15 EditTextAndroid::EditTextAndroid() { 16 auto env = cocos2d::JniHelper::getEnv(); 17 18 jclass cls = env->FindClass("org/red/tools/RedEditText"); 19 assert(cls != NULL); 20 21 jmethodID ctor = env->GetMethodID(cls, "<init>", "()V"); 22 assert(ctor != NULL); 23 24 this->_object = env->NewObject(cls, ctor); 25 env->NewGlobalRef(this->_object); 26 } 27 28 EditTextAndroid::~EditTextAndroid() { 29 auto env = cocos2d::JniHelper::getEnv(); 30 env->DeleteGlobalRef(this->_object); 31 } 32 33 JniMethodInfo EditTextAndroid::getJavaMethod(const char* name, const char* param) { 34 JniMethodInfo info; 35 bool isHave = JniHelper::getMethodInfo(info, "org/red/tools/RedEditText", name, param); 36 assert(isHave); 37 return info; 38 } 39 40 void EditTextAndroid::setString(const std::string& str) { 41 auto info = getJavaMethod("setString", "(Ljava/lang/String;)V"); 42 jstring jstr = info.env->NewStringUTF(str.c_str()); 43 info.env->CallVoidMethod(this->_object, info.methodID, jstr); 44 } 45 46 std::string EditTextAndroid::getString() { 47 auto info = getJavaMethod("getString", "()Ljava/lang/String;"); 48 auto jstr = (jstring)info.env->CallObjectMethod(this->_object, info.methodID); 49 50 jboolean isCopy; 51 auto chars = info.env->GetStringUTFChars(jstr, &isCopy); 52 std::string str(chars); 53 if(isCopy == JNI_TRUE) { 54 info.env->ReleaseStringUTFChars(jstr, chars); 55 } 56 info.env->DeleteLocalRef(jstr); 57 return str; 58 } 59 60 void EditTextAndroid::setPosition(const Vec2& pos) { 61 EditText::setPosition(pos); 62 setPositionAndroid(); 63 } 64 65 void EditTextAndroid::setContentSize(const Size& size) { 66 EditText::setContentSize(size); 67 setContentSizeAndroid(); 68 } 69 70 void EditTextAndroid::setPositionAndroid() { 71 if(isRunning()) { 72 auto pos = convertToWorldSpace(Vec2(0, getContentSize().height)); 73 auto info = getJavaMethod("setPosition", "(II)V"); 74 auto visHeight = Director::getInstance()->getVisibleSize().height; 75 info.env->CallVoidMethod(this->_object, info.methodID, jint(pos.x), jint(visHeight - pos.y)); 76 } 77 } 78 79 void EditTextAndroid::setContentSizeAndroid() { 80 if(isRunning()) { 81 auto realSize = SizeApplyAffineTransform(getContentSize(), getNodeToWorldAffineTransform()); 82 auto info = getJavaMethod("setContentSize", "(II)V"); 83 info.env->CallVoidMethod(this->_object, info.methodID, jint(realSize.width), jint(realSize.height)); 84 } 85 } 86 87 void EditTextAndroid::onEnter() { 88 EditText::onEnter(); 89 setPositionAndroid(); 90 setContentSizeAndroid(); 91 } 92 93 extern "C" { 94 JNIEXPORT void JNICALL Java_org_red_tools_RedEditText_nativeOnTextChanged(JNIEnv *env, jobject javaThis, jstring jstr) { 95 jboolean isCopy; 96 auto chars = env->GetStringUTFChars(jstr, &isCopy); 97 std::string str(chars); 98 if(isCopy == JNI_TRUE) { 99 env->ReleaseStringUTFChars(jstr, chars); 100 } 101 log("[Red] textChanged: %s", str.c_str()); 102 } 103 } 1 #ifndef __CocosAndroidStudio__EditTextFactory__ 2 #define __CocosAndroidStudio__EditTextFactory__ 3 4 #include "EditText.h" 5 #include <map> 6 #include "platform/android/jni/JniHelper.h" 7 8 class EditTextFactory { 9 public: 10 static EditTextFactory* getInstance(); 11 12 EditText* createEditText(); 13 EditText* getEditTextByJobject(jobject obj); 14 15 private: 16 EditTextFactory(); 17 18 std::map<jobject, EditText*> _map; 19 }; 20 21 #endif /* defined(__CocosAndroidStudio__EditTextFactory__) */ 1 #include "EditTextFactory.h" 2 #include "EditTextAndroid.h" 3 #include <string> 4 #include "cocos2d.h" 5 6 EditTextFactory::EditTextFactory() {} 7 8 EditTextFactory* EditTextFactory::getInstance() { 9 static EditTextFactory instance; 10 return &instance; 11 } 12 13 EditText* EditTextFactory::createEditText() { 14 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) 15 auto edit = EditTextAndroid::create(); 16 auto jobj = edit->_object; 17 _map.insert(std::pair<jobject, EditText*>(jobj, edit)); 18 return edit; 19 #endif 20 21 return nullptr; 22 } 23 24 EditText* EditTextFactory::getEditTextByJobject(jobject obj) { 25 return _map[obj]; 26 } 1 package org.red.tools; 2 3 import org.cocos2dx.lib.Cocos2dxActivity; 4 5 import android.graphics.Color; 6 import android.os.Handler; 7 import android.os.Looper; 8 import android.text.Editable; 9 import android.text.TextWatcher; 10 import android.util.Log; 11 import android.view.inputmethod.EditorInfo; 12 import android.widget.EditText; 13 import android.widget.FrameLayout; 14 15 public class RedEditText { 16 17 private EditText _edit; 18 19 public RedEditText() { 20 new Handler(Looper.getMainLooper()).post(new Runnable() { 21 @Override 22 public void run() { 23 RedEditText.this._edit = new EditText(Cocos2dxActivity.getContext()); 24 EditText edit = RedEditText.this._edit; 25 //edit.setBackgroundDrawable(null); 26 edit.setTextColor(Color.rgb(255, 255, 255)); 27 edit.setMaxLines(1); 28 edit.setSingleLine(); 29 edit.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); 30 Cocos2dxActivity activity = (Cocos2dxActivity)(Cocos2dxActivity.getContext()); 31 FrameLayout root = (FrameLayout)activity.findViewById(android.R.id.content).getRootView(); 32 root.addView(edit); 33 34 edit.addTextChangedListener(new TextWatcher() { 35 @Override 36 public void onTextChanged(CharSequence s, int start, int before, int count) { 37 nativeOnTextChanged(s.toString()); 38 } 39 40 @Override 41 public void beforeTextChanged(CharSequence s, int start, int count, int after) {} 42 @Override 43 public void afterTextChanged(Editable s) {} 44 }); 45 } 46 }); 47 } 48 49 public void setString(final String str) { 50 Log.e("red", str); 51 new Handler(Looper.getMainLooper()).post(new Runnable() { 52 @Override 53 public void run() { 54 _edit.setText(str); 55 } 56 }); 57 } 58 59 public String getString() { 60 return _edit.getText().toString(); 61 } 62 63 public void setContentSize(final int w, final int h) { 64 new Handler(Looper.getMainLooper()).post(new Runnable() { 65 @Override 66 public void run() { 67 FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)_edit.getLayoutParams(); 68 params.width = w; 69 params.height = h; 70 _edit.setLayoutParams(params); 71 } 72 }); 73 } 74 75 public void setPosition(final int x, final int y) { 76 new Handler(Looper.getMainLooper()).post(new Runnable() { 77 @Override 78 public void run() { 79 FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)_edit.getLayoutParams(); 80 params.leftMargin = x; 81 params.topMargin = y; 82 _edit.setLayoutParams(params); 83 } 84 }); 85 } 86 87 private native void nativeOnTextChanged(String s); 88 89 } 最后是luabinding,吐血推荐教程:http://www.cocos.com/doc/tutorial/show?id=1295 这是我绑定之后的代码,可以直接用: 1 #include "base/ccConfig.h" 2 #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 3 #ifndef __RedBindings_h__ 4 #define __RedBindings_h__ 5 6 #ifdef __cplusplus 7 extern "C" { 8 #endif 9 #include "tolua++.h" 10 #ifdef __cplusplus 11 } 12 #endif 13 14 int register_all_RedBindings(lua_State* tolua_S); 15 16 17 18 19 20 21 22 23 24 #endif // __RedBindings_h__ 25 #endif //#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 1 #include "lua_RedBindings_auto.hpp" 2 #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 3 #include "RedBindings.h" 4 #include "tolua_fix.h" 5 #include "LuaBasicConversions.h" 6 7 8 int lua_RedBindings_EditText_setString(lua_State* tolua_S) 9 { 10 int argc = 0; 11 EditText* cobj = nullptr; 12 bool ok = true; 13 14 #if COCOS2D_DEBUG >= 1 15 tolua_Error tolua_err; 16 #endif 17 18 19 #if COCOS2D_DEBUG >= 1 20 if (!tolua_isusertype(tolua_S,1,"EditText",0,&tolua_err)) goto tolua_lerror; 21 #endif 22 23 cobj = (EditText*)tolua_tousertype(tolua_S,1,0); 24 25 #if COCOS2D_DEBUG >= 1 26 if (!cobj) 27 { 28 tolua_error(tolua_S,"invalid 'cobj' in function 'lua_RedBindings_EditText_setString'", nullptr); 29 return 0; 30 } 31 #endif 32 33 argc = lua_gettop(tolua_S)-1; 34 if (argc == 1) 35 { 36 std::string arg0; 37 38 ok &= luaval_to_std_string(tolua_S, 2,&arg0, "EditText:setString"); 39 if(!ok) 40 { 41 tolua_error(tolua_S,"invalid arguments in function 'lua_RedBindings_EditText_setString'", nullptr); 42 return 0; 43 } 44 cobj->setString(arg0); 45 lua_settop(tolua_S, 1); 46 return 1; 47 } 48 luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "EditText:setString",argc, 1); 49 return 0; 50 51 #if COCOS2D_DEBUG >= 1 52 tolua_lerror: 53 tolua_error(tolua_S,"#ferror in function 'lua_RedBindings_EditText_setString'.",&tolua_err); 54 #endif 55 56 return 0; 57 } 58 int lua_RedBindings_EditText_getString(lua_State* tolua_S) 59 { 60 int argc = 0; 61 EditText* cobj = nullptr; 62 bool ok = true; 63 64 #if COCOS2D_DEBUG >= 1 65 tolua_Error tolua_err; 66 #endif 67 68 69 #if COCOS2D_DEBUG >= 1 70 if (!tolua_isusertype(tolua_S,1,"EditText",0,&tolua_err)) goto tolua_lerror; 71 #endif 72 73 cobj = (EditText*)tolua_tousertype(tolua_S,1,0); 74 75 #if COCOS2D_DEBUG >= 1 76 if (!cobj) 77 { 78 tolua_error(tolua_S,"invalid 'cobj' in function 'lua_RedBindings_EditText_getString'", nullptr); 79 return 0; 80 } 81 #endif 82 83 argc = lua_gettop(tolua_S)-1; 84 if (argc == 0) 85 { 86 if(!ok) 87 { 88 tolua_error(tolua_S,"invalid arguments in function 'lua_RedBindings_EditText_getString'", nullptr); 89 return 0; 90 全部评论
专题导读
上一篇:添加文件【COCOS2DX-LUA脚本开发之十三】解决lua项目编译Android出现getdatafromfilef ...发布时间:2022-07-22下一篇:Lua类和类继承实现发布时间:2022-07-22热门推荐
热门话题
阅读排行榜
|
请发表评论