android适配右到左布局注意事项
呜呼,伊朗的项目终于做完了,大部分都是在整理右到左布局的需求。好在android sdk 从API17(Android4.2)开始支持右到左布局的需求,但是会有很多坑需要去填。
Android中的大部分组件是支持右到左布局的,只需要在Androidmanifest中配置如下:
<application....android:supportsRtl="true"></application>
我们先看一个demo,MainActivity对应的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.test.activity.MainActivity"><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"android:background="@color/fastlane_background"/><TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center_vertical"android:text="hello world "android:background="@color/selected_background"/>
</LinearLayout>
我们可以动态设置系统的语言来模仿用户环境,如下将app的配置设置为波斯语,当然,最简单的是到手机设置中直接设置当前语言为波斯语(设置有风险,语言需谨慎~~):
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Locale locale = new Locale("fa_IR");//fa_IR是波斯语(伊朗)的代码Locale.setDefault(locale);Configuration config = new Configuration();config.locale = locale;DisplayMetrics dm = getResources().getDisplayMetrics();getResources().updateConfiguration(config, dm);setContentView(R.layout.activity_main);}
以下是没有加android:supportsRtl="true"的布局,很正常不过的布局吧?
那么加了之后呢?
显然toolbar的内容已经反过来了。且慢,textview好像没有任何变化?_?,难道textview不支持右到左布局?
1、textview gravity的右到左布局适配
大家知道textview有一个gravity的属性,其中可以通过以下两种方式指定textview的内容在左边还是在右边
1) left,right:绝对位置,指定内容显示在textview的左边还是右边,这个比较好理解
2) start,end:这个大家应该见过,该值作用的结果与系统布局方向有关,如下所示:
举一反三,drawableStart,drawableEnd和layout_marginStart,layout_marginEnd以及layout_toStartOf,layout_toEndOf等也是同理,都是相对布局方向而言的。
有同学马上就会想到,直接指定textview的gravity为start不就解决上面的问题了嘛!修改后的textview如下:
<TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center_vertical|start"android:text="hello world "android:background="@color/selected_background"/>
效果如下:
不对啊,这不按套路出牌呀。内容怎么还是在左边。。。
同学们发现没有,内容是英文的,而伊朗是用波斯语言,会不会与语言有关呢?我们再加一个textView显示波斯语言的:
<TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@color/fti_left_color"android:gravity="center_vertical|start"android:text="فارسی" />
结果如下:
是不是反过来了?由于波斯语言是右到左显示的,所以其内容也是默认居右边的。这说明,textview 的内容布局位置与文字显示的方向相关的。为了与伊朗用户的用户习惯保持一致,就算textview的内容是英文的,也应该居右边显示,那么如何做到呢?
Android提供了Java代码动态获取当前布局方向,如下:
/*** * @param context* @return 如果是右到左布局,返回true*/public boolean isRtl(Context context) {return context.getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;}
然后我们可以通过该方法设置textView的gravity
textView.setGravity(isRtl(this) ? Gravity.RIGHT:Gravity.LEFT);
结果大家显然都知道了,这里就不列出来了。
但是这样还是觉得很麻烦,有没有更便捷的属性?有!
name | description | 描述 |
---|---|---|
android:layoutDirection | attribute for setting the direction of a component’s layout | 设置组件的布局排列方向 |
android:textDirection | attribute for setting the direction of a component’s text | 设置组件的文字排列方向 |
android:textAlignment | attribute for setting the alignment of a component’s text | 设置文字的对齐方式 |
getLayoutDirectionFromLocale() | method for getting the Locale-specified direction | 获取指定地区的惯用布局方式 |
其中,android:layoutDirection和android:textDirection的值有:
value | type | description |
---|---|---|
inherit | int |
Horizontal layout direction is inherited 继承水平方向 |
rtl | int |
Horizontal layout direction is from Right to Left 布局方向是右到左 |
ltr | int |
Horizontal layout direction is from Left to Right 布局方向是左到右 |
locale | int |
Horizontal layout direction is deduced from the default language script for the locale 从区域设置的默认语言脚本推导出水平布局方向 |
android:textAlignment的值有:
Constant | value | Description |
---|---|---|
center | 4 |
Center the paragraph, for example: ALIGN_CENTER. 居中 |
gravity | 1 |
Default for the root view. The gravity determines the alignment, ALIGN_NORMAL, ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 由view通过gravity属性定义对齐方式 |
inherit | 0 |
Default. 默认 |
textEnd | 3 |
Align to the end of the paragraph, for example: ALIGN_OPPOSITE. 与段落的末尾对齐 |
textStart | 2 |
Align to the start of the paragraph, for example: ALIGN_NORMAL. 与段落的开头对齐 |
viewEnd | 6 |
Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved layoutDirection is LTR, and ALIGN_LEFT otherwise. 与view的末尾对齐, |
viewStart | 5 |
Align to the start of the view, which is ALIGN_LEFT if the view’s resolved layoutDirection is LTR, and ALIGN_RIGHT otherwise. 与view的开头对齐 |
还是原来的布局,这里多加一行
<TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:background="@color/selected_background"android:gravity="center_vertical|start"android:textDirection="locale"android:text="hello world " />
效果如下
要给辣么多个textview添加该属性,多麻烦!没事,有全局的设置~~
<resources><style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar" ><item name="android:textViewStyle">@style/TextDirection</item></style><style name="TextDirection" parent="android:Widget.TextView"><item name="android:textDirection">locale</item></style>
</resources>
然后在Androidmanifest文件中引用该style
<application......android:supportsRtl="true"android:theme="@style/AppTheme">.......</application>
类似的还有EditText
<style name="AppTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">.....<item name="editTextStyle">@style/EditTextStyle</item></style><style name="EditTextStyle" parent="@android:style/Widget.EditText"><item name="android:textAlignment">viewStart</item><item name="android:gravity">start</item><item name="android:textDirection">locale</item></style>
2、组件之间的相对位置
在处理组件之间的相对位置,一般会用到layout_marginLeft,layout_marginRight或者layout_toLeftOf,layout_toRightOf等。那么如果你的app需要兼顾右到左布局的时候,这些布局约束就不合适了,需要用Start,End来代替Left,Right。天呐,如果有几十上百个布局文件,不是要改死程序员了么?别怕,Android studio已经为我们提供了一键适配右到左布局的需求,如下图所示
然后会弹出一个对话框,直接点击“run”
接着会提示你哪些需要添加适配属性的,直接点击“Do Refactor”
如果有不需要修改的,可以选中不修改的文件,或者某一行代码。选择Remove即可
这样我们的布局文件就自定添加start、end属性。
如果布局中使用了drawableStart或者drawableEnd属性就需要注意了,需要考虑图标是否需要跟随布局方向变化而变化,例如作为方向标示的就不应该变化位置,因此需要依旧使用drawableLeft和drawableRight
3、布局约束的右到左布局适配
在开发中,有时需要动态移动view的位置,一般的做法是修改view的layout,设置x,y轴或者设置marginLayoutParams等,当然还有一般的动画。
还是我们的mainActivity,对应的布局有两个textview1,textview2,点击textview2会修改textview1的位置,对应的代码如下:
private TextView textview1, textview2;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
// Locale locale = new Locale("fa_IR");
// Locale.setDefault(locale);
// Configuration config = new Configuration();
// config.locale = locale;
// DisplayMetrics dm = getResources().getDisplayMetrics();
// getResources().updateConfiguration(config, dm);setContentView(R.layout.activity_main);textview1 = findViewById(R.id.textview1);textview2 = findViewById(R.id.textview2);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.textview2) {ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) textview1.getLayoutParams();marginLayoutParams.leftMargin += 20 ;marginLayoutParams.topMargin += 10;textview1.setLayoutParams(marginLayoutParams);}}
效果如果,我们成功的移动了textview1
我们再解除被注释掉的代码,再试试看:
怎么没有往右下角移动?_? 不是已经设置了leftMargin了么,怎么只有topMargin有效?
在右到左布局下,Android的会从右到左依次绘制view,虽然我们设置了leftMargin,但是,系统在绘制view的时候会以rightMargin约束条件为准,如下图所示,所以就导致了leftMargin无效的问题。
需要注意的是,在右到左布局下,系统坐标并没有改变,getLeft,getTop,getX,getY等值没有发生变化。
所以,我们需要稍作修改
@Overridepublic void onClick(View v) {if (v.getId() == R.id.textview2) {ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) textview1.getLayoutParams();marginLayoutParams.rightMargin += 20 ;marginLayoutParams.topMargin += 10;textview1.setLayoutParams(marginLayoutParams);}}
结果如下:
那如果在右到左布局下,textview的移动动画与左到右布局下一致呢?很简单,同时设置leftMargin和rightMargin即可:
@Overridepublic void onClick(View v) {if (v.getId() == R.id.textview2) {int screenWidth = getWindowManager().getDefaultDisplay().getWidth() ;ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) textview1.getLayoutParams();marginLayoutParams.leftMargin += 20;marginLayoutParams.rightMargin = screenWidth- textview1.getWidth()-marginLayoutParams.leftMargin ;marginLayoutParams.topMargin += 10;textview1.setLayoutParams(marginLayoutParams);}}
效果如下
总结
1、如果使用到drawableLeft、drawableRight属性,请确定图标是否需要跟随系统布局方法改变而改变,如果是,请修改为drawableStart、drawableEnd;反之不用
2、在代码中需要动态修改view的布局约束,例如marginLayoutParams,layoutParams.setMargins()等,需要同时考虑left和right,或者采用修改layout的方式。
3、获取view的位置可以通过以下代码:
int[] location = new int[2];view.getLocationOnScreen(location);float x = location[0];float y = location[1]
4、在relativelayout中添加layout rule的时候,用START_OF
、END_OF代替LEFT_OF、RIGHT_OF。
5、在右到左布局下,其坐标布局方式不变,getLeft,getRight等不变。变的是布局约束,view的绘制受right(start)约束。
6、一些方向图标,重新做一个相对方向的放到 drawable-ldrtl-xxxhdpi 包下
7、textview,editText需要对内容做RTL处理,设置style,详情见第一节
8、在显示文件路径时候,如果包含波斯语,会导致路径显示错误的情况,需要在string的前后加上\u202D 和\u202C
String content = "sdcard\\فارسی\\3D\\فارسی.mp3";textview1.setText("\u202D"+content+"\u202C");
或者使用如下代码
public String getLTRString(String content) {return BidiFormatter.getInstance().unicodeWrap(content, TextDirectionHeuristics.LTR);}
实际显示如下:
9、如果需要修改view的位置,请不要使用setX,setY方式。推荐采用ViewGroup.MarginLayoutParams来设置margin,或者采用layout的方式。同时需要注意该约束是相对父view而言的。
android适配右到左布局注意事项相关推荐
- android 布局排排,[android]如何使LinearLayout布局从右向左水平排列,而不是从左向右排列...
方法1:利用android:layout_weight android:layout_width="match_parent" android:layout_height=&quo ...
- 如何使LinearLayout布局从右向左水平排列,而不是从左向右排列
方法1:利用android:layout_weight <LinearLayout xmlns:android="http://schemas.android.com/apk/res/ ...
- android 居右属性,使用layoutDirection属性设置布局靠左或靠右
通过设置layoutDirection属性值为mx.core.LayoutDirection.RTL(右到左)或mx.core.LayoutDirection.LTR(左到右),使布局为靠左或靠右(如 ...
- android ui布局适配,Android适配全面总结(一)----屏幕适配
前言 Android适配是一个老生常谈的问题,很多程序员觉得很恶心,不愿意做适配,但是又不得不做.然后老板说,这位兄弟,做好了,今天晚饭给你加个鸡腿,然后程序员开始找各种资料,忙活起来了,最终在苦逼的 ...
- Android直播软件搭建左滑右滑清屏控件
Android直播软件搭建左滑右滑清屏控件 最近在迭代直播软件搭建功能时,项目中之前的左滑清屏是用ViewPager实现的.这次迭代遇到一个布局层次导致的点击失效问题,继续用ViewPager的话改动 ...
- Android反向进度条(ProgressBar)的实现——从右到左的进度条
Android反向进度条(ProgressBar)--从右到左的进度条 前言: 最近在项目中需要使用到反向进度条,在网上查了些资料,感觉对自己作用不大,于是自定义样式,实现了反向进度条. 1. 第一步 ...
- android 波斯文排序,Android 4.2原生支持从右到左的文字排列格式
Android 4.1(Jelly Bean) 在 TextView 和 EditText 元素里对"双向文字顺序"提供了有限的功能支持,允许应用程序在编辑和显示字符的时候,能够同 ...
- Android ProgressBar 反向进度条/进度条从右到左走
近期的项目,有个需求须要使用条状图显示比例,而且右对齐,见下图: 我想到了使用进度条,这样不就不须要在代码动态绘制条状了,省了非常多活. 那么进度条如何从右向左显示呢? 方案一: 将ProgressB ...
- android tablerow 间隔,android-如何使TableRow从右到左
如何从右到左向TableRow添加视图?默认模式为从左到右.我在TableLayout和TableRow中都尝试了android:gravity =" right"和android ...
最新文章
- 作为一名准程序员,谈一下现实和未来
- IX1000系统信息收集
- 华为USG地址池方式的NAPT和NAT Server配置案例
- 知道你用linux可视文件系统为什么搜索不到文件吗?(隐藏文件夹搜不到!!要用find . -name “xxx“命令)
- 如何发送html email,如何发送HTML电子邮件?
- 吴恩达作业10:用卷积神经网络识别人脸happy(基于Keras)
- dbml mysql_MySQL数据库笔记二:数据类型及数据库操作
- iPhone XR再降价:64GB到手最低仅需4149元
- 【选手分享】你想知道的比赛思路这里都有!速查收!
- 23种设计模式(二十二)行为变化之命令模式
- java sftp工具类_Java代码--SFTP工具类
- 播放html5视频黑屏,播放视频黑屏 · Issue #91 · surmon-china/vue-video-player · GitHub
- ERP软件实施要提供那些环境条件
- ubuntu安装wine版微信
- Linux系统下查看dsdt table
- 微信内网页链接被多人投诉导致拦截的解决方案
- 修改华为路由器lan端口
- Android第三方SDK集成 —— 极光推送
- linux解压zip、tar压缩包
- STM32三种BOOT模式
热门文章
- python入门必备指南-致Python初学者 Anaconda入门使用指南完整版
- mysql中创建用户并授权_MySQL中创建用户及授权[转]
- python面向对象类属性_python面向对象之类属性和类方法案例分析
- 利用CStopWatch计算并显示小车运行速度
- ege函数库_EGE图形库|EGE图形库下载v12.11 最新版 附使用教程 - 欧普软件下载
- C# .net core 解决ToLower中缺少CultureInfo格式重载
- 移动端手势操作--两点同时点击的实现方案
- 设置共享,实现Linux和Windows之间的共享
- POJ 3982 序列 塔尔苏斯问题解决
- JSTL 格式化 BigDecimal对象