Android-EditText 自定义带删除功能的EditText

我们经常在一些应用中见到输入框带有删除功能,今天我们就来实现这个功能(文字组织能力不强,大家随便看看)。主要是记录一下自己的学习经历,如果对大家有帮助,我会更开心的。 先上图: 实现要点: 1、当输入框为空时,删除按钮隐藏; 2、当输入框不为空时,显示删除按钮。 核心代码: `001.``package` `com.example.view;` <div class="line alt2"> `002.`<span class="content"><span class="block">`import` `com.example.ui.R;`</span></span> </div> <div class="line alt1"> `003.`<span class="content"><span class="block">`import` `android.content.Context;`</span></span> </div> <div class="line alt2"> `004.`<span class="content"><span class="block">`import` `android.graphics.Rect;`</span></span> </div> <div class="line alt1"> `005.`<span class="content"><span class="block">`import` `android.graphics.drawable.Drawable;`</span></span> </div> <div class="line alt2"> `006.`<span class="content"><span class="block">`import` `android.text.Editable;`</span></span> </div> <div class="line alt1"> `007.`<span class="content"><span class="block">`import` `android.text.TextWatcher;`</span></span> </div> <div class="line alt2"> `008.`<span class="content"><span class="block">`import` `android.util.AttributeSet;`</span></span> </div> <div class="line alt1"> `009.`<span class="content"><span class="block">`import` `android.view.MotionEvent;`</span></span> </div> <div class="line alt2"> `010.`<span class="content"><span class="block">`import` `android.view.View;`</span></span> </div> <div class="line alt1"> `011.`<span class="content"><span class="block">`import` `android.widget.EditText;`</span></span> </div> <div class="line alt2"> `012.`<span class="content"><span class="block">`import` `android.widget.Toast;`</span></span> </div> <div class="line alt1"> `013.`<span class="content"><span class="block">`import` `android.view.View.OnFocusChangeListener;;`</span></span> </div> <div class="line alt2"> `014.`<span class="content"><span class="block">`public` `class` `EditTextWithDelete ``extends` `EditText ``implements` `OnFocusChangeListener{`</span></span> </div> <div class="line alt1"> `015.`<span class="content"><span class="block">`private` `Drawable imgEnable;`</span></span> </div> <div class="line alt2"> `016.`<span class="content"><span class="block">`private` `Context context;`</span></span> </div> <div class="line alt1"> `017.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `018.`<span class="content"><span class="block">`public` `EditTextWithDelete(Context context) {`</span></span> </div> <div class="line alt1"> `019.`<span class="content"><span class="block">`super``(context);`</span></span> </div> <div class="line alt2"> `020.`<span class="content"><span class="block">`this``.context = context;`</span></span> </div> <div class="line alt1"> `021.`<span class="content"><span class="block">`init();`</span></span> </div> <div class="line alt2"> `022.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `023.`<span class="content"><span class="block">`public` `EditTextWithDelete(Context context, AttributeSet attrs, ``int` `defStyle) {`</span></span> </div> <div class="line alt2"> `024.`<span class="content"><span class="block">`super``(context, attrs, defStyle);`</span></span> </div> <div class="line alt1"> `025.`<span class="content"><span class="block">`this``.context = context;`</span></span> </div> <div class="line alt2"> `026.`<span class="content"><span class="block">`init();`</span></span> </div> <div class="line alt1"> `027.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `028.`<span class="content"><span class="block">`public` `EditTextWithDelete(Context context, AttributeSet attrs) {`</span></span> </div> <div class="line alt1"> `029.`<span class="content"><span class="block">`super``(context, attrs);`</span></span> </div> <div class="line alt2"> `030.`<span class="content"><span class="block">`this``.context = context;`</span></span> </div> <div class="line alt1"> `031.`<span class="content"><span class="block">`init();`</span></span> </div> <div class="line alt2"> `032.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `033.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `034.`<span class="content"><span class="block">`private` `void` `init() {`</span></span> </div> <div class="line alt1"> `035.`<span class="content"><span class="block">`//获取图片资源`</span></span> </div> <div class="line alt2"> `036.`<span class="content"><span class="block">`imgEnable = context.getResources().getDrawable(R.drawable.delete);`</span></span> </div> <div class="line alt1"> `037.`<span class="content"><span class="block">`addTextChangedListener(``new` `TextWatcher() {`</span></span> </div> <div class="line alt2"> `038.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `039.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt2"> `040.`<span class="content"><span class="block">`public` `void` `onTextChanged(CharSequence s, ``int` `start, ``int` `before, ``int` `count) {`</span></span> </div> <div class="line alt1"> `041.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `042.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `043.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `044.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt1"> `045.`<span class="content"><span class="block">`public` `void` `beforeTextChanged(CharSequence s, ``int` `start, ``int` `count,`</span></span> </div> <div class="line alt2"> `046.`<span class="content"><span class="block">`int` `after) {`</span></span> </div> <div class="line alt1"> `047.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `048.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `049.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `050.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt1"> `051.`<span class="content"><span class="block">`public` `void` `afterTextChanged(Editable s) {`</span></span> </div> <div class="line alt2"> `052.`<span class="content"><span class="block">`setDrawable();`</span></span> </div> <div class="line alt1"> `053.`<span class="content"><span class="block">`Toast.makeText(context, getText(), ``10``).show();`</span></span> </div> <div class="line alt2"> `054.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `055.`<span class="content"><span class="block">`});`</span></span> </div> <div class="line alt2"> `056.`<span class="content"><span class="block">`setDrawable();`</span></span> </div> <div class="line alt1"> `057.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `058.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `059.`<span class="content"><span class="block">`/**`</span></span> </div> <div class="line alt2"> `060.`<span class="content"><span class="block">`* 设置删除图片`</span></span> </div> <div class="line alt1"> `061.`<span class="content"><span class="block">`*/`</span></span> </div> <div class="line alt2"> `062.`<span class="content"><span class="block">`private` `void` `setDrawable() {`</span></span> </div> <div class="line alt1"> `063.`<span class="content"><span class="block">`if``(length() == ````) {`</span></span> </div> <div class="line alt2"> `064.`<span class="content"><span class="block">`setCompoundDrawablesWithIntrinsicBounds(``null``, ``null``, ``null``, ``null``);`</span></span> </div> <div class="line alt1"> `065.`<span class="content"><span class="block">`}``else` `{`</span></span> </div> <div class="line alt2"> `066.`<span class="content"><span class="block">`setCompoundDrawablesWithIntrinsicBounds(``null``, ``null``, imgEnable, ``null``);`</span></span> </div> <div class="line alt1"> `067.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `068.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `069.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `070.`<span class="content"><span class="block">`/**`</span></span> </div> <div class="line alt1"> `071.`<span class="content"><span class="block">`* event.getX() 获取相对应自身左上角的X坐标`</span></span> </div> <div class="line alt2"> `072.`<span class="content"><span class="block">`* event.getY() 获取相对应自身左上角的Y坐标`</span></span> </div> <div class="line alt1"> `073.`<span class="content"><span class="block">`* getWidth() 获取控件的宽度`</span></span> </div> <div class="line alt2"> `074.`<span class="content"><span class="block">`* getTotalPaddingRight() 获取删除图标左边缘到控件右边缘的距离`</span></span> </div> <div class="line alt1"> `075.`<span class="content"><span class="block">`* getPaddingRight() 获取删除图标右边缘到控件右边缘的距离`</span></span> </div> <div class="line alt2"> `076.`<span class="content"><span class="block">`* getWidth() - getTotalPaddingRight() 计算删除图标左边缘到控件左边缘的距离`</span></span> </div> <div class="line alt1"> `077.`<span class="content"><span class="block">`* getWidth() - getPaddingRight() 计算删除图标右边缘到控件左边缘的距离`</span></span> </div> <div class="line alt2"> `078.`<span class="content"><span class="block">`*/`</span></span> </div> <div class="line alt1"> `079.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt2"> `080.`<span class="content"><span class="block">`public` `boolean` `onTouchEvent(MotionEvent event) {`</span></span> </div> <div class="line alt1"> `081.`<span class="content"><span class="block">`if``(imgEnable != ``null` `&& event.getAction() == MotionEvent.ACTION_UP) {`</span></span> </div> <div class="line alt2"> `082.`<span class="content"><span class="block">`int` `x = (``int``) event.getX() ;`</span></span> </div> <div class="line alt1"> `083.`<span class="content"><span class="block">`//判断触摸点是否在水平范围内`</span></span> </div> <div class="line alt2"> `084.`<span class="content"><span class="block">`boolean` `isInnerWidth = (x &gt; (getWidth() - getTotalPaddingRight())) &&`</span></span> </div> <div class="line alt1"> `085.`<span class="content"><span class="block">`(x &lt; (getWidth() - getPaddingRight()));`</span></span> </div> <div class="line alt2"> `086.`<span class="content"><span class="block">`//获取删除图标的边界,返回一个Rect对象`</span></span> </div> <div class="line alt1"> `087.`<span class="content"><span class="block">`Rect rect = imgEnable.getBounds();`</span></span> </div> <div class="line alt2"> `088.`<span class="content"><span class="block">`//获取删除图标的高度`</span></span> </div> <div class="line alt1"> `089.`<span class="content"><span class="block">`int` `height = rect.height();`</span></span> </div> <div class="line alt2"> `090.`<span class="content"><span class="block">`int` `y = (``int``) event.getY();`</span></span> </div> <div class="line alt1"> `091.`<span class="content"><span class="block">`//计算图标底部到控件底部的距离`</span></span> </div> <div class="line alt2"> `092.`<span class="content"><span class="block">`int` `distance = (getHeight() - height) /``2``;`</span></span> </div> <div class="line alt1"> `093.`<span class="content"><span class="block">`//判断触摸点是否在竖直范围内(可能会有点误差)`</span></span> </div> <div class="line alt2"> `094.`<span class="content"><span class="block">`//触摸点的纵坐标在distance到(distance+图标自身的高度)之内,则视为点中删除图标`</span></span> </div> <div class="line alt1"> `095.`<span class="content"><span class="block">`boolean` `isInnerHeight = (y &gt; distance) && (y &lt; (distance + height));`</span></span> </div> <div class="line alt2"> `096.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `097.`<span class="content"><span class="block">`if``(isInnerWidth && isInnerHeight) {`</span></span> </div> <div class="line alt2"> `098.`<span class="content"><span class="block">`setText(``""``);`</span></span> </div> <div class="line alt1"> `099.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `100.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `101.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `102.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `103.`<span class="content"><span class="block">`return` `super``.onTouchEvent(event);`</span></span> </div> <div class="line alt2"> `104.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `105.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt2"> `106.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt1"> `107.`<span class="content"><span class="block">`protected` `void` `finalize() ``throws` `Throwable {`</span></span> </div> <div class="line alt2"> `108.`<span class="content"><span class="block">`super``.finalize();`</span></span> </div> <div class="line alt1"> `109.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `110.`<span class="content"><span class="block">`@Override`</span></span> </div> <div class="line alt1"> `111.`<span class="content"><span class="block">`public` `void` `onFocusChange(View v, ``boolean` `hasFocus) {`</span></span> </div> <div class="line alt2"> `112.`<span class="content"><span class="block">`if``(hasFocus) {`</span></span> </div> <div class="line alt1"> `113.`<span class="content"><span class="block">`setDrawable();`</span></span> </div> <div class="line alt2"> `114.`<span class="content"><span class="block">`}``else` `{`</span></span> </div> <div class="line alt1"> `115.`<span class="content"><span class="block">`setCompoundDrawablesWithIntrinsicBounds(``null``, ``null``, ``null``, ``null``);`</span></span> </div> <div class="line alt2"> `116.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt1"> `117.`<span class="content"><span class="block">`}`</span></span> </div> <div class="line alt2"> `118.`<span class="content"><span class="block"> </span></span> </div> <div class="line alt1"> `119.`<span class="content"><span class="block">`}`</span></span> </div> 代码注释很清楚,相信以大家的水平都会看的懂的。在这边,我就不多做解释了。如果有不明白的,可以给我留言,大家交流交流。 ...

2016年11月7日 · 5 分钟 · 天边的星星

Android WebView 与登录状态保持一致,建立SESSION会话

在登陆界面获取验证码的时候: ``` `new Thread(){ @Override public void run() { try { SharedPreferences spf = getSharedPreferences(<span class=“hljs-string”>“Cookie”</span>, Context<span class=“hljs-preprocessor”>.MODE</span>_PRIVATE)<span class=“hljs-comment”>;</span> HttpClient client = new DefaultHttpClient()&lt;span class="hljs-comment">;&lt;/span> HttpGet get = new HttpGet(Gloable&lt;span class="hljs-preprocessor">.DOLOAD&lt;/span>+&lt;span class="hljs-string">"code.gif"&lt;/span>)&lt;span class="hljs-comment">;&lt;/span> HttpResponse response = client&lt;span class="hljs-preprocessor">.execute&lt;/span>(get)&lt;span class="hljs-comment">;&lt;/span> Cookie cookie = ((AbstractHttpClient) client)&lt;span class="hljs-preprocessor">.getCookieStore&lt;/span>()&lt;span class="hljs-preprocessor">.getCookies&lt;/span>()&lt;span class="hljs-preprocessor">.get&lt;/span>(&lt;span class="hljs-number">0&lt;/span>)&lt;span class="hljs-comment">;&lt;/span> String sessionId = cookie&lt;span class="hljs-preprocessor">.getValue&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> SharedPreferences&lt;span class="hljs-preprocessor">.Editor&lt;/span> editor = spf&lt;span class="hljs-preprocessor">.edit&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> editor&lt;span class="hljs-preprocessor">.putString&lt;/span>(&lt;span class="hljs-string">"sessionId"&lt;/span>, sessionId)&lt;span class="hljs-comment">;&lt;/span> String cookieString = cookie&lt;span class="hljs-preprocessor">.getName&lt;/span>()+&lt;span class="hljs-string">"="&lt;/span>+cookie&lt;span class="hljs-preprocessor">.getValue&lt;/span>()+ &lt;span class="hljs-string">";domain="&lt;/span>+cookie&lt;span class="hljs-preprocessor">.getDomain&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> Log&lt;span class="hljs-preprocessor">.e&lt;/span>(&lt;span class="hljs-string">"test"&lt;/span>, &lt;span class="hljs-string">"cookieString:"&lt;/span>+cookieString)&lt;span class="hljs-comment">;&lt;/span> editor&lt;span class="hljs-preprocessor">.putString&lt;/span>(&lt;span class="hljs-string">"cookieString"&lt;/span>, cookieString)&lt;span class="hljs-comment">;&lt;/span> editor&lt;span class="hljs-preprocessor">.commit&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> Log&lt;span class="hljs-preprocessor">.i&lt;/span>(&lt;span class="hljs-string">"info"&lt;/span>, &lt;span class="hljs-string">"b--JSESSIONID="&lt;/span> + sessionId)&lt;span class="hljs-comment">;&lt;/span> if (response&lt;span class="hljs-preprocessor">.getStatusLine&lt;/span>()&lt;span class="hljs-preprocessor">.getStatusCode&lt;/span>() == &lt;span class="hljs-number">200&lt;/span>) { byte[] bytes = EntityUtils&lt;span class="hljs-preprocessor">.toByteArray&lt;/span>(response&lt;span class="hljs-preprocessor">.getEntity&lt;/span>())&lt;span class="hljs-comment">;&lt;/span> final Bitmap bitmap = BitmapFactory&lt;span class="hljs-preprocessor">.decodeByteArray&lt;/span>(bytes, &lt;span class="hljs-number">0&lt;/span>, bytes&lt;span class="hljs-preprocessor">.length&lt;/span>)&lt;span class="hljs-comment">;&lt;/span> runOnUiThread(new Runnable() { public void run() { Drawable drawable = new BitmapDrawable(bitmap)&lt;span class="hljs-comment">;&lt;/span> iv_showCode&lt;span class="hljs-preprocessor">.setBackgroundDrawable&lt;/span>(drawable)&lt;span class="hljs-comment">;&lt;/span> } })&lt;span class="hljs-comment">;&lt;/span> } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e&lt;span class="hljs-preprocessor">.printStackTrace&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> } catch (IOException e) { // TODO Auto-generated catch block e&lt;span class="hljs-preprocessor">.printStackTrace&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> } } }&lt;span class="hljs-preprocessor">.start&lt;/span>()&lt;span class="hljs-comment">;&lt;/span>` 在webview加载url之前: ``` `SharedPreferences spf = getSharedPreferences(&lt;span class="hljs-string">"Cookie"&lt;/span>, Context&lt;span class="hljs-preprocessor">.MODE&lt;/span>_PRIVATE)&lt;span class="hljs-comment">;&lt;/span> CookieSyncManager&lt;span class="hljs-preprocessor">.createInstance&lt;/span>(this)&lt;span class="hljs-comment">;&lt;/span> CookieManager cookieManager = CookieManager&lt;span class="hljs-preprocessor">.getInstance&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> String cookieString = spf&lt;span class="hljs-preprocessor">.getString&lt;/span>(&lt;span class="hljs-string">"cookieString"&lt;/span>, &lt;span class="hljs-string">""&lt;/span>)&lt;span class="hljs-comment">;&lt;/span> cookieManager&lt;span class="hljs-preprocessor">.setCookie&lt;/span>(url, cookieString)&lt;span class="hljs-comment">;&lt;/span> CookieSyncManager&lt;span class="hljs-preprocessor">.getInstance&lt;/span>()&lt;span class="hljs-preprocessor">.sync&lt;/span>()&lt;span class="hljs-comment">;&lt;/span> webview&lt;span class="hljs-preprocessor">.loadUrl&lt;/span>(url)&lt;span class="hljs-comment">;&lt;/span>` android客户端通过httpClient或者httpUrlConnection进行登录后,为了把登录状态同步到webView中,这时需要进行cookie的同步 一.cookie同步方式 下面是登录线程: public class LoginThread extends Thread{ private Handler loginHandler; public LoginThread(Handler loginHandler) { this.loginHandler = loginHandler; } @Override public void run() { List cookieLst = new ArrayList(); HttpParams httpParams = new BasicHttpParams(); ConnManagerParams.setMaxTotalConnections(httpParams, 5); ConnManagerParams.setTimeout(httpParams, 151000); HttpConnectionParams.setSoTimeout(httpParams, 101000); HttpConnectionParams.setTcpNoDelay(httpParams, true); HttpPost httpPost = new HttpPost(“http://192.168.1.107/cookie/login.php”); List nvPairs = new ArrayList(); nvPairs.add(new BasicNameValuePair(“name”, “lisi”)); nvPairs.add(new BasicNameValuePair(“age”,”22″)); nvPairs.add(new BasicNameValuePair(“gender”, “男”)); ...

2016年10月11日 · 4 分钟 · 天边的星星

史上最详细的Android原生APP中添加ReactNative 进行混合开发教程

背景 React Native出来已经一段时间了,相对来说也算稳定了,在很多的企业中都实际使用他们,混合开发已经是未来的一种趋势,混合开发中使用的技术很多,不外乎Html5、JS框架通过一定的技术和原始交互,目前主流混合开发React Native、Cordova、APICloud、MUI、AppCan、Sencha Touch、jQuery Mobile等等(其他的小伙伴们自己收集),目前网上写教程的人很多,但是React Native更新速度很快,根据他们的教程,中间会遇到各种问题,今天我和大家一起踩踩各种坑,让小伙伴们快速集成到自己的APP中。后续持续更新,反馈发邮件411437734@qq.com共同探讨。 集成步骤 参考官方文档->react native 文档 本文使用开发环境 Android studio 注意最新的React Native支持的最新的SDK为16(android4.1) npm环境,小伙伴们自己安装 nodeJS自己安装,可以参考官方文档安装环境,有问题可以发411437734@qq.com沟通 创建Android项目(已有项目跳过) 打开Android studio 输入项目名称,选择项目目录,点击next 至此项目创建完成(需要注意的是最新的React Native支持最新SDK版本为16 android4.1) React Native集成到上面我们创建的ReactNativeAPPDemo中 参考Facebook react native文档 进入项目根目录,添加JS到项目中-点击Android studio中的Terminal(如下图)  分别执行一下语句 npm init npm install –save react react-native curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig init 主要根据提醒生成package.json文件 curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig 下载.flowconfig文件 参考图片 查看项目中有node_modules,说明react和react native 安装完成 在项目根目录添加.flowconfig 参考下图  也可以手动创建在浏览器打开https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig网址复制内容创建文件 ReactNativeAppDemo配置相关内容 添加"start": “node node_modules/react-native/local-cli/cli.js start” 到package.json 文件下 scripts标签 修改前修改后 添加index.android.js文件到项目中 ...

2016年9月30日 · 2 分钟 · 天边的星星

Android实用工具

Android 命令 ( adb push 文件 目标文件 ) adb shell pm install -r “/data/local/tmp/xxxx” pkg: /data/local/tmp/xxxx 启动指定Activity $ adb shell am start -n “package/package.Activity” -a android.intent.action.MAIN -c android.intent.category.LAUNCHER Android 动态权限 final private int REQUEST_CODE_ASK_PERMISSIONS = 123; private void insertDummyContactWrapper() { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) { showMessageOKCancel(“You need to allow access to Contacts”, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); } }); return; } requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); return; } insertDummyContact(); } ...

2016年9月27日 · 2 分钟 · 天边的星星

Android 使用Gradle打包APP名称和版本号

需求:我想根据不同的类型,打包不同的版本号,在Android中怎么实现? 例如:release(发布)版本号 1.0.1,debug(测试)版本号1.0.1.20160924 在Android开发中,我们会不断的进行版本打包,打包分为2类: 1、release(正式发布上线版) 2、debug(测试版)。 我们可以通过每次打包前修改build.gradle中android->versionName实现,作为一个程序员,有不断探索的精神,能懒就懒(重复没有意义的工作懒的做)。 知识介绍 1、gradle中定义变量和函数 通过关键字 def 来定义 例如:def versionStr = "1.0.1" def myFunction() { return "xxxxx" } 2、gradle中时间使用 new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"); 这行代码的意思是“当前时间是UTC时区,已yyyyMMdd格式化时间输出” 3、gradle中variant.mergedFlavor使用 variant.mergedFlavor.versionName 表示修改打包时versionName的值 4、gradle中variant.outputs使用 variant.outputs表示输出相关配置 下面是我的build.gradle文件 apply plugin: &#39;com.android.application&#39; apply plugin: &#39;android-apt&#39; //定义时间 def releaseTime() { return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC")) } //设置发布的显示的版本号 def getVersionName(){ return "1.2.0" } android { compileSdkVersion 23 buildToolsVersion "24.0.0" defaultConfig { applicationId "com.xxx.xxxx" minSdkVersion 14 targetSdkVersion 23 versionCode 3 //versionName getVersionName() } buildTypes { debug { buildConfigField("boolean","API_DEBUG","true") minifyEnabled false proguardFiles getDefaultProguardFile(&#39;proguard-android.txt&#39;), &#39;proguard-rules.pro&#39; } release { buildConfigField("boolean","API_DEBUG","false") minifyEnabled false proguardFiles getDefaultProguardFile(&#39;proguard-android.txt&#39;), &#39;proguard-rules.pro&#39; } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } //修改打包不能成功配置 lintOptions { checkReleaseBuilds false abortOnError false } //配置自定义打包名称 applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile def fileName if (outputFile != null && outputFile.name.endsWith(&#39;.apk&#39;)) { if (variant.buildType.name.equals(&#39;release&#39;)) { variant.mergedFlavor.versionName = getVersionName() fileName = "XXXX_<span class="katex math inline">{variant.mergedFlavor.versionName}_release.apk" } else if (variant.buildType.name.equals(&#39;debug&#39;)) { variant.mergedFlavor.versionName = getVersionName()+"."+releaseTime() fileName = "XXXX_</span>{variant.mergedFlavor.versionName}_debug.apk" } output.outputFile = new File(outputFile.parent, fileName) } } } } dependencies { compile fileTree(include: [&#39;*.jar&#39;], dir: &#39;libs&#39;) testCompile &#39;junit:junit:4.12&#39; } tasks.withType(JavaCompile) { options.encoding = "UTF-8" } 大家可以举一反三 例如想修改versionCode可以这么写 variant.mergedFlavor.versionCode = xxxx; 现在试试吧! ...

2016年9月24日 · 1 分钟 · 天边的星星

Android Studio 2.0+发布APK出现ExternalSystemException: String index out of range: -123错误

前阵子Android Studio 2.0正式版发布了,很高兴的就升到了最新版本。 一编译就出现400多个错误提示,Gradle2.0编译速度也让人泪奔,哎,可能是技术太渣不懂那些配置,晚晚加班也没时间学习,还好debug方式编译正常运行 今天老大叫发布APK,使用Android Studio2.0 release APK 时出现ExternalSystemException: String index out of range: -123错误提示, 搞了一个晚上终于解决了,记忆不好,在这里记录一下,怕以后出现类似问题忘记怎么解决。 解决方法: 在主项目build.gradle的android标签里加上 lintOptions { checkReleaseBuilds **false ** *// Or, if you prefer, you can continue to check for errors in release builds, ** // but continue the build even when errors are found: * abortOnError **false **} 如图: ![](http://img.blog.csdn.net/20160423152939548?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 转自:http://blog.csdn.net/jia__/article/details/51226475

2016年9月22日 · 1 分钟 · 天边的星星

android Shape只显示指定边框用法

&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt; &lt;!-- focused --&gt; &lt;item android:drawable="@drawable/orderboard_detail_tab_middle_selected" android:state_checked="true" /&gt; &lt;item android:drawable="@drawable/orderboard_detail_tab_middle_selected" android:state_selected="true" /&gt; &lt;!-- default --&gt; &lt;item &gt; &lt;layer-list xmlns:android="http://schemas.android.com/apk/res/android"&gt; &lt;item android:left="-1dp" android:right="-1dp" &gt; &lt;shape android:shape="rectangle"&gt; &lt;solid android:color="@color/text_color_white" /&gt; &lt;stroke android:width="1dp" android:color="@color/text_color_blue" /&gt; &lt;padding android:left="0dp" android:right="0dp" /&gt; &lt;corners android:radius="0dp"/&gt; &lt;/shape&gt; &lt;/item&gt; &lt;/layer-list&gt; &lt;/item&gt; &lt;/selector&gt; 上面执行的结果:只画上下线 [![QQ20160830-0@2x](http://www.etongwl.com/images/2016/08/QQ20160830-0@2x-300x289.png)](http://www.etongwl.com/images/2016/08/QQ20160830-0@2x.png)

2016年8月30日 · 1 分钟 · 天边的星星

Android Toast花式使用

![](http://upload-images.jianshu.io/upload_images/828721-e0fc168c7e6ce054.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 之前写过一篇没时间解释了,快使用Snackbar!——Android Snackbar花式使用指南。Toast的自定义使用原理与其类似。 1.Toast源码分析 老规矩,我们先去看Toast的源码。 Toast有两种显示布局方式,一种最常见调用Toast.makeText(),看源码是这样写的 `&lt;span class="hljs-function">&lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-keyword">static&lt;/span> Toast &lt;span class="hljs-title">makeText&lt;/span>(&lt;span class="hljs-params">Context context, CharSequence text, @Duration &lt;span class="hljs-keyword">int&lt;/span> duration&lt;/span>) &lt;/span>{ Toast result = &lt;span class="hljs-keyword">new&lt;/span> Toast(context); LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = inflate.inflate(com.android.&lt;span class="hljs-keyword">internal&lt;/span>.R.layout.transient_notification, &lt;span class="hljs-keyword">null&lt;/span>); TextView tv = (TextView)v.findViewById(com.android.&lt;span class="hljs-keyword">internal&lt;/span>.R.id.message); tv.setText(text); result.mNextView = v; result.mDuration = duration; &lt;span class="hljs-keyword">return&lt;/span> result; }` transient_notification这个布局文件代码是这样的 `&lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">LinearLayout&lt;/span> &lt;span class="hljs-attribute">xmlns:android&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/apk/res/android"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:orientation&lt;/span>=&lt;span class="hljs-value">"vertical"&lt;/span> &lt;span class="hljs-attribute">android:background&lt;/span>=&lt;span class="hljs-value">"?android:attr/toastFrameBackground"&lt;/span>&gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">TextView&lt;/span> &lt;span class="hljs-attribute">android:id&lt;/span>=&lt;span class="hljs-value">"@android:id/message"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"wrap_content"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"wrap_content"&lt;/span> &lt;span class="hljs-attribute">android:layout_weight&lt;/span>=&lt;span class="hljs-value">"1"&lt;/span> &lt;span class="hljs-attribute">android:layout_gravity&lt;/span>=&lt;span class="hljs-value">"center_horizontal"&lt;/span> &lt;span class="hljs-attribute">android:textAppearance&lt;/span>=&lt;span class="hljs-value">"@style/TextAppearance.Toast"&lt;/span> &lt;span class="hljs-attribute">android:textColor&lt;/span>=&lt;span class="hljs-value">"@color/bright_foreground_dark"&lt;/span> &lt;span class="hljs-attribute">android:shadowColor&lt;/span>=&lt;span class="hljs-value">"#BB000000"&lt;/span> &lt;span class="hljs-attribute">android:shadowRadius&lt;/span>=&lt;span class="hljs-value">"2.75"&lt;/span> /&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">LinearLayout&lt;/span>&gt;&lt;/span>` 那么我们想要修改Toast的文字消息样式,其实就是修改Toast根布局和message这个TextView。 ...

2016年8月25日 · 4 分钟 · 天边的星星

android webView网页表单自动登录(单点登录)

今天帮助网友解决了一个在应用中登录后进应用的网页自动登录。 在这里分享给大家,希望能帮助更多的人。直接上代码: /** * 网页自动登录 * http://haohailai.taobao.com/ * @author xiehaibo * */ public class MainActivity extends Activity { private WebView webView1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView1 = (WebView) findViewById(R.id.webView1); // 设置支持JavaScript脚本 WebSettings webSettings = webView1.getSettings(); webSettings.setJavaScriptEnabled(true); // 设置可以访问文件 webSettings.setAllowFileAccess(true); // 设置支持缩放 webSettings.setBuiltInZoomControls(true); // 设置WebViewClient webView1.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { Log.d("admin", "网页加载完了"); String uname = "帐号"; String password = "密码"; // 加载完了再调用js登录代码 view.loadUrl("javascript: {" + "document.getElementById('username').value = '" + uname + "';" + "document.getElementById('password').value = '" + password + "';" + "var frms = document.getElementsByName('tableForm');" + "frms[0].submit(); };"); // 登录成功后加载框取消 super.onPageFinished(view, url); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Log.d("admin", "网页开始加载"); // 在这里可以创建一个加载框。。。 super.onPageStarted(view, url, favicon); } }); webView1.loadUrl("网页地址,包含登录表单"); } } 注意的是: ...

2016年8月22日 · 1 分钟 · 天边的星星

android获取web服务器端session并验证登陆

传统网页实现用户登陆一般采用session或cookie记录用户基本信息又或者两者结合起来使用。android也可以采用session实现用户登陆验证并记录用户登陆状态时的基本信息,session是在服务器端的;而类似cookie的记录方式,则可以在客户端采用xml文件记录用户基本信息,重要数据则可以加密存放客户端。android实现的session登陆功能与网页请求不同的是,网页形式的一次成功的登陆请求后,再点击其他页面时,session一直是存在的,在一定时间内是有效的;而采用android客户端请求的一次成功登陆后,再次发送新的请求,则会产生新的session,而不是原来的。这就需要记录session的id号,并在整个请求过程中都记录并传递这个id号,才能保证session的一致性。 以获取php session为例,主要思路实现分为客户端与服务器端3个步骤。 附件:源码下载 1.)客户端(ANDROID) 建立一个名为GetWebSession的android项目,编写GetWebSession.java,LoginSuccessActivity.java,GetUserInfoActivity.java三个activity类。 GetWebSession.java主要是实现布局界面以及发送用户名和密码到php服务器端验证,如果验证成功则跳转到LoginSuccessActivity.java类。GetWebSession.java主要涉及到与服务器端连接请求,对从服务器端返回的json数据(如用户id,session等)进行解析,并存入HashMap,传递到LoginSuccessActivity.java 代码如下: [view plain](http://www.yoyong.com/archives/178#)[copy to clipboard](http://www.yoyong.com/archives/178#)[print](http://www.yoyong.com/archives/178#)[?](http://www.yoyong.com/archives/178#) - <span class="keyword">package</span> com.login.main; - <span class="keyword">import</span> java.io.IOException; - <span class="keyword">import</span> java.io.UnsupportedEncodingException; - <span class="keyword">import</span> java.util.ArrayList; - <span class="keyword">import</span> java.util.HashMap; - <span class="keyword">import</span> java.util.List; - <span class="keyword">import</span> org.apache.http.HttpEntity; - <span class="keyword">import</span> org.apache.http.HttpResponse; - <span class="keyword">import</span> org.apache.http.client.ClientProtocolException; - <span class="keyword">import</span> org.apache.http.client.entity.UrlEncodedFormEntity; - <span class="keyword">import</span> org.apache.http.client.methods.HttpPost; - <span class="keyword">import</span> org.apache.http.impl.client.DefaultHttpClient; - <span class="keyword">import</span> org.apache.http.message.BasicNameValuePair; - <span class="keyword">import</span> org.apache.http.protocol.HTTP; - <span class="keyword">import</span> org.apache.http.util.EntityUtils; - <span class="keyword">import</span> org.json.JSONException; - <span class="keyword">import</span> org.json.JSONObject; - <span class="keyword">import</span> android.app.Activity; - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.content.Intent; - <span class="keyword">import</span> android.os.Bundle; - <span class="keyword">import</span> android.view.View; - <span class="keyword">import</span> android.view.View.OnClickListener; - <span class="keyword">import</span> android.widget.Button; - <span class="keyword">import</span> android.widget.EditText; - <span class="keyword">import</span> android.widget.Toast; - <span class="keyword">public</span> <span class="keyword">class</span> GetWebSession <span class="keyword">extends</span> Activity { - <span class="comment">/** Called when the activity is first created. */</span> - <span class="keyword">private</span> EditText user; - <span class="keyword">private</span> EditText password; - <span class="keyword">private</span> Button loginBtn; - <span class="keyword">private</span> Button logoutBtn; - <span class="comment">//主要是记录用户会话过程中的一些用户的基本信息</span> - <span class="keyword">private</span> HashMap<String, String> session =<span class="keyword">new</span> HashMap<String, String>(); - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onCreate(Bundle savedInstanceState) { - <span class="keyword">super</span>.onCreate(savedInstanceState); - setContentView(R.layout.main); - user=(EditText)findViewById(R.id.user); - password=(EditText)findViewById(R.id.password); - loginBtn=(Button)findViewById(R.id.loginBtn); - loginBtn.setOnClickListener(loginClick); - logoutBtn=(Button)findViewById(R.id.logoutBtn); - logoutBtn.setOnClickListener(logoutClick); - } - OnClickListener loginClick=<span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) { - <span class="comment">// TODO Auto-generated method stub</span> - <span class="keyword">if</span>(checkUser()){ - Toast.makeText(v.getContext(), <span class="string">&#8220;用户登录成功!&#8221;</span>, Toast.LENGTH_SHORT).show(); - Context context = v.getContext(); - Intent intent = <span class="keyword">new</span> Intent(context, - LoginSuccessActivity.<span class="keyword">class</span>); - <span class="comment">//传递session参数,在用户登录成功后为session初始化赋值,即传递HashMap的值</span> - Bundle map = <span class="keyword">new</span> Bundle(); - map.putSerializable(<span class="string">&#8220;sessionid&#8221;</span>, session); - intent.putExtra(<span class="string">&#8220;session&#8221;</span>, map); - context.startActivity(intent); <span class="comment">// 跳转到成功页面</span> - } - <span class="keyword">else</span> - Toast.makeText(v.getContext(), <span class="string">&#8220;用户验证失败!&#8221;</span>, Toast.LENGTH_SHORT).show(); - } - }; - OnClickListener logoutClick=<span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) { - <span class="comment">// TODO Auto-generated method stub</span> - System.exit(<span class="number"></span>); - } - }; - <span class="keyword">private</span> <span class="keyword">boolean</span> checkUser(){ - String username=user.getText().toString(); - String pass=password.getText().toString(); - DefaultHttpClient mHttpClient = <span class="keyword">new</span> DefaultHttpClient(); - HttpPost mPost = <span class="keyword">new</span> HttpPost(<span class="string">&#8220;http://10.0.2.2/web/php/login.php&#8221;</span>); - <span class="comment">//传递用户名和密码相当于</span> - <span class="comment">//http://10.0.2.2/web/php/login.php?username=&#8221;&password=&#8221;</span> - List<BasicNameValuePair> pairs = <span class="keyword">new</span> ArrayList<BasicNameValuePair>(); - pairs.add(<span class="keyword">new</span> BasicNameValuePair(<span class="string">&#8220;username&#8221;</span>, username)); - pairs.add(<span class="keyword">new</span> BasicNameValuePair(<span class="string">&#8220;password&#8221;</span>, pass)); - <span class="keyword">try</span> { - mPost.setEntity(<span class="keyword">new</span> UrlEncodedFormEntity(pairs, HTTP.UTF_8)); - } <span class="keyword">catch</span> (UnsupportedEncodingException e) { - <span class="comment">// TODO Auto-generated catch block</span> - e.printStackTrace(); - } - <span class="keyword">try</span> { - HttpResponse response = mHttpClient.execute(mPost); - <span class="keyword">int</span> res = response.getStatusLine().getStatusCode(); - <span class="keyword">if</span> (res == <span class="number">200</span>) { - HttpEntity entity = response.getEntity(); - <span class="keyword">if</span> (entity != <span class="keyword">null</span>) { - String info = EntityUtils.toString(entity); - System.out.println(<span class="string">&#8220;info&#8212;&#8212;&#8212;&#8211;&#8220;</span>+info); - <span class="comment">//以下主要是对服务器端返回的数据进行解析</span> - JSONObject jsonObject=<span class="keyword">null</span>; - <span class="comment">//flag为登录成功与否的标记,从服务器端返回的数据</span> - String flag=<span class="string">&#8220;&#8221;</span>; - String name=<span class="string">&#8220;&#8221;</span>; - String userid=<span class="string">&#8220;&#8221;</span>; - String sessionid=<span class="string">&#8220;&#8221;</span>; - <span class="keyword">try</span> { - jsonObject = <span class="keyword">new</span> JSONObject(info); - flag = jsonObject.getString(<span class="string">&#8220;flag&#8221;</span>); - name = jsonObject.getString(<span class="string">&#8220;name&#8221;</span>); - userid = jsonObject.getString(<span class="string">&#8220;userid&#8221;</span>); - sessionid = jsonObject.getString(<span class="string">&#8220;sessionid&#8221;</span>); - } <span class="keyword">catch</span> (JSONException e) { - <span class="comment">// TODO Auto-generated catch block</span> - e.printStackTrace(); - } - <span class="comment">//根据服务器端返回的标记,判断服务端端验证是否成功</span> - <span class="keyword">if</span>(flag.equals(<span class="string">&#8220;success&#8221;</span>)){ - <span class="comment">//为session传递相应的值,用于在session过程中记录相关用户信息</span> - session.put(<span class="string">&#8220;s_userid&#8221;</span>, userid); - session.put(<span class="string">&#8220;s_username&#8221;</span>, name); - session.put(<span class="string">&#8220;s_sessionid&#8221;</span>, sessionid); - <span class="keyword">return</span> <span class="keyword">true</span>; - } - <span class="keyword">else</span>{ - <span class="keyword">return</span> <span class="keyword">false</span>; - } - } - <span class="keyword">else</span>{ - <span class="keyword">return</span> <span class="keyword">false</span>; - } - } - } <span class="keyword">catch</span> (ClientProtocolException e) { - <span class="comment">// TODO Auto-generated catch block</span> - e.printStackTrace(); - } <span class="keyword">catch</span> (IOException e) { - <span class="comment">// TODO Auto-generated catch block</span> - e.printStackTrace(); - } - <span class="keyword">return</span> <span class="keyword">false</span>; - } - } LoginSuccessActivity.java主要获取php的session唯一的标识id以及用户的一些基本信息,session id则作为本次用户登录状态在服务器的唯一标识,即确定用户的唯一状态进行相关操作。LoginSuccessActivity.java类的方法与GetWebSession.java类似。其主要功能是获取session id后再次发送session id到服务器进行验证,根据封装的session数据验证用户操作权限等。 代码如下: ...

2016年8月22日 · 14 分钟 · 天边的星星