Android 坐标系与视图坐标系图解分析
1. Android坐标系
在Android中,将屏幕的最左上角顶点作为Android坐标系的原点
从原点向右是X轴的正方向,从原点向下是Y轴的正方向
View提供了getLocationOnScreen( int[] location)方法来获取在整个屏幕内的绝对坐标,该坐标值为View左上角的坐标。注意该View的坐标值是从屏幕左上角开始获取的,所以也包括了通知栏的高度
该方法的具体实现
代码如下 | 复制代码 |
/** * Computes the coordinates of this view on the screen. The argument * must be an array of two integers. After the method returns, the array * contains the x and y location in that order. * * @param location an array of two integers in which to hold the coordinates */ publicvoidgetLocationOnScreen(@Size(2)int[] location) { getLocationInWindow(location); finalAttachInfo info = mAttachInfo; if(info !=null) { location[0] += info.mWindowLeft; location[1] += info.mWindowTop; } } |
可看到,传入的int[]数组中,location[0]代表的是X轴坐标,location[1]代表的Y轴坐标
这里还有个getLocationInWindow方法,作用是获取View在当前窗口内的绝对坐标
我们在通过MotionEvent类中的getRawX(),getRawY()方法获取的坐标同样也属于这种Android坐标系里的坐标
2. 视图坐标系
Android中的视图坐标系,描述的是子视图与其父视图中的位置关系
和Android坐标系一样,视图坐标系也是以原点向右为X轴正方向,以原点向下为Y轴正方向,与Android坐标系不同的是,视图坐标系的原点是以父视图左上角的位置为原点
如上图中,对于Button来说,父视图LinearLayout左上角就是视图坐标系的原点(0,0)
我们通过MotionEvent类中的getX()、getY()方法所获得的就是视图坐标系的坐标
在Android中,系统提供了很多获取坐标值、相对距离等方法
View提供的API
•getTop():获取View顶边到其父布局顶边的距离
•getLeft():获取View左边到其父布局左边的距离
•getRight():获取View右边到其父布局左边的距离
•getBottom():获取View底边到其父布局顶边的距离
MotionEvent提供的API
• getX():获取点击位置离View左边的距离
• getY():获取点击位置离View顶边的距离
• getRawX():获取点击位置离屏幕左边的距离
• getRawY():获取点击位置离屏幕顶边的距离
本文详细解析了网络爬虫案例,非常有用,不懂的同学可以看看网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常被称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本,已被广泛应用于互联网领域。搜索引擎使用网络爬虫抓取Web网页、文档甚至图片、音频、视频等资源,通过相应的索引技术组织这些信息,提供给搜索用户进行查询。网络爬虫也为中小站点的推广提供了有效的途径,网站针对搜索引擎爬虫的优化曾风靡一时。
网络爬虫的基本工作流程如下:
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
当然,上面说的那些我都不懂,以我现在的理解,我们请求一个网址,服务器返回给我们一个超级大文本,而我们的浏览器可以将这个超级大文本解析成我们说看到的华丽的页面
那么,我们只需要把这个超级大文本看成一个足够大的String 字符串就OK了。
下面是我的代码
| |
代码如下 | 复制代码 |
packagemain.spider; importorg.jsoup.Jsoup; importorg.jsoup.nodes.Document; importorg.jsoup.nodes.Element; importorg.jsoup.select.Elements; importjava.io.IOException; /** * Created by 1755790963 on 2017/3/10. */ publicclassSecond { publicstaticvoidmain(String[] args)throwsIOException { System.out.println("begin"); Document document = Jsoup.connect("http://tieba.baidu.com/p/2356694991").get(); String selector="div[class=d_post_content j_d_post_content clearfix]"; Elements elements = document.select(selector); for(Element element:elements){ String word= element.text(); if(word.indexOf("@")>0){ word=word.substring(0,word.lastIndexOf("@")+7); System.out.println(word); } System.out.println(word); } } } |
我在这里使用了apache公司所提供的jsoup jar包,jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
在代码里,我们可以直接使用Jsoup类,并.出Jsoup的connect()方法,这个方法返回一个org.jsoup.Connection对象,参数则是网站的url地址,Connection对象有一个get()方法返回Document对象
document对象的select方法可以返回一个Elements对象,而Elements对象正式Element对象的集合,但select()方法需要我们传入一个String参数,这个参数就是我们的选择器
String selector="div[class=d_post_content j_d_post_content clearfix]";
我们的选择器语法类似于jquery的选择器语法,可以选取html页面中的元素,选择好后,就可以便利Elements集合,通过Element的text()方法获取html中的代码
这样,一个最简单的网络爬虫就写完了。
我选择的网址是 豆瓣网,留下你的邮箱,我会给你发邮件 这样一个百度贴吧,我扒的是所有人的邮箱地址
附上结果:
本文介绍了Android中使用 AutoCompleteTextView 实现手机号格式化附带清空历史的操作,非常实用,有兴趣的同学可以参考一下有个小伙伴遇到了这样一个问题,就是AutoCompleteTextView实现自动填充的功能。同时要具备手机格式化的功能。下拉列表最后一行是有个清除历史的功能。可是点击“清除历史”却把文字要设置进去AutoCompleteTextView中。这样的效果显然很糟糕。所以我就写了这样一个简单的demo。来帮助遇到这种问题的朋友解决这样一个问题。二话不多说直接上代码。
布局文件(activity_main.xml)代码如下:
代码如下 | 复制代码 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Please input:"/> <AutoCompleteTextView android:id="@+id/actv" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
|
java文件(MainActivity.java)代码如下:
代码如下 | 复制代码 |
importandroid.app.Activity; importandroid.os.Bundle; importandroid.text.Editable; importandroid.text.Selection; importandroid.text.TextWatcher; importandroid.view.View; importandroid.widget.AdapterView; importandroid.widget.AdapterView.OnItemClickListener; importandroid.widget.ArrayAdapter; importandroid.widget.AutoCompleteTextView; importandroid.widget.EditText; importandroid.widget.TextView; importandroid.widget.Toast; publicclassMainActivityextendsActivity { privateAutoCompleteTextView mAutoCompleteTextView; privateString[] mAutoStrs =newString[] {"138 0013 8000","13800138001", "13800138002","13800138003","13800138004","138 0013 800清除记录"}; privateString mBeforeTextChangedStr =""; publicvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.actv); ArrayAdapter android.R.layout.simple_dropdown_item_1line, mAutoStrs); mAutoCompleteTextView.setAdapter(_arrayAdapter); mAutoCompleteTextView.setThreshold(1);// 设置输入一个字符就提示 mAutoCompleteTextView.setOnItemClickListener(newOnItemClickListener() { @Override publicvoidonItemClick(AdapterView arg0, View arg1,intarg2, longarg3) { String _clearStr =""; if(arg1instanceofTextView) { _clearStr = ((TextView) arg1).getText().toString(); } if(_clearStr.equals("138 0013 800清楚记录")) { mAutoCompleteTextView.setText(mBeforeTextChangedStr); Editable _editable = mAutoCompleteTextView.getText(); Selection.setSelection(_editable, _editable.length()); Toast.makeText(MainActivity.this,"清除成功了!", Toast.LENGTH_LONG).show(); } } }); phoneNumAddSpaceOne(mAutoCompleteTextView); } /** * 手机号格式化代码 * * @param editText * EditText对象 */ publicvoidphoneNumAddSpaceOne(finalEditText editText) { editText.addTextChangedListener(newTextWatcher() { privateintstart; privateintbefore; privateStringBuilder stringBuilder; @Override publicvoidonTextChanged(CharSequence s,intstart,intbefore, intcount) { this.start = start; this.before = before; } @Override publicvoidbeforeTextChanged(CharSequence s,intstart,intcount, intafter) { } @Override publicvoidafterTextChanged(Editable s) { String _str = s.toString(); if(!isNumeric(_str.replace(" ",""))) { return; } mBeforeTextChangedStr = _str; // 手机号格式化xxx xxxx xxxx if(s ==null|| s.length() ==0) return; if(stringBuilder ==null) { stringBuilder =newStringBuilder(); }else{ stringBuilder.delete(0, stringBuilder.length()); } for(inti =0; i < s.length(); i++) { if(i !=3&& i !=8&& s.charAt(i) ==' ') { continue; }else{ stringBuilder.append(s.charAt(i)); if((stringBuilder.length() ==4|| stringBuilder .length() ==9)&& stringBuilder.charAt(stringBuilder.length() -1) !=' ') { stringBuilder.insert(stringBuilder.length() -1,' '); } } } if(!stringBuilder.toString().equals(s.toString())) { intindex = start +1; if(stringBuilder.charAt(start) ==' ') { if(before ==0) { index++; }else{ index--; } }else{ if(before ==1) { index--; } } editText.setText(stringBuilder.toString()); editText.setSelection(index); } } }); } /** * 判断字符串是否是数字 * * @param str * 需要判断的字符串 * @return */ publicbooleanisNumeric(String str) { for(inti = str.length(); --i >=0;) { intchr = str.charAt(i); if(chr<48|| chr="">57) returnfalse; } returntrue; } } |
本文给大家介绍了android动态设置app当前运行语言的方法,非常有用,不懂的同学可以考虑
android开发中有时候碰到切换语言的需求,这时候需要通过代码动态改变当前运行语言。
代码如下 | 复制代码 |
packagecom.example.androidtest;
importjava.util.Locale;
importandroid.os.Bundle; importandroid.app.Activity; importandroid.content.Intent; importandroid.content.res.Configuration; importandroid.content.res.Resources; importandroid.util.DisplayMetrics; importandroid.view.Menu; importandroid.view.View; importandroid.widget.Button;
publicclassMainActivityextendsActivity {
@Override protectedvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Button btnLang = (Button) findViewById(R.id.btn); // 按下按钮改变语言类型,在“简体中文”和“英文”之间切换 btnLang.setOnClickListener(newView.OnClickListener() {
@Override publicvoidonClick(View v) { // 获取当前Locale(包含语言信息) Locale curLocale = getResources().getConfiguration().locale;
// 判断语言类型,有以下两种判断方式
// 方法一,通过Locale的equals方法 // public boolean equals (Object object) // Returns true if object is a locale with the same language, country and variant. if(curLocale.equals(Locale.SIMPLIFIED_CHINESE)) { setLang(Locale.ENGLISH); }else{ setLang(Locale.SIMPLIFIED_CHINESE); }
// 方法二,通过语言码,getLanguage()方法可以获得对应语言码 // public String getLanguage () // Returns the language code for this Locale or the empty string if no language was set. // if (curLocale.getLanguage().equals(Locale.SIMPLIFIED_CHINESE.getLanguage())) { // setLang(Locale.ENGLISH); // } else { // setLang(Locale.SIMPLIFIED_CHINESE); // } } }); }
privatevoidsetLang(Locale l) { // 获得res资源对象 Resources resources = getResources(); // 获得设置对象 Configuration config = resources.getConfiguration(); // 获得屏幕参数:主要是分辨率,像素等。 DisplayMetrics dm = resources.getDisplayMetrics(); // 语言 config.locale = l; resources.updateConfiguration(config, dm);
// 刷新activity才能马上奏效 startActivity(newIntent().setClass(MainActivity.this, MainActivity.class)); MainActivity.this.finish(); }
@Override publicbooleanonCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); returntrue; }
} |
通过下面一行代码获得当前语言信息
Locale curLocale = getResources().getConfiguration().locale;
判断语言和设置语言部分有详细注释,就不做过多解释啦!
资源文件需要支持多语言环境,这样才能看到切换语言的效果!
创建values-en文件夹,并创建英文版的strings.xml文件。
相关文章
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
- 深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
- TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
- 因此,正确的原子操作是真正被执行过的。是物理执行。在当前事务中确实能看到插入的记录。最后只不过删除了。但是AUTO_INCREMENT不会应删除而改变值。1、为什么auto_increament没有回滚?因为innodb的auto_increament的...2014-05-31
android.os.BinderProxy cannot be cast to com解决办法
本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20- 这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
- 下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
- 首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20
- 下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
- 索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引 ...2014-06-07
用Intel HAXM给Android模拟器Emulator加速
Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。 周末试玩了一下在Eclipse中使...2016-09-20- 在安卓开发时我碰到一个问题就是需要实现全屏,但又需要我们来判断出用户是使用了全屏或非全屏了,下面我分别找了两段代码,大家可参考。 先来看一个android屏幕全屏实...2016-09-20
Android开发中布局中的onClick简单完成多控件时的监听的利与弊
本文章来为各位介绍一篇关于Android开发中布局中的onClick简单完成多控件时的监听的利与弊的例子,希望这个例子能够帮助到各位朋友. 首先在一个控件加上这么一句:and...2016-09-20