假设我有一个在不同资源文件夹中具有三种不同布局的活动。例如:
layout-land/my_act.xml
layout-xlarge/my_act.xml
layout-xlarge-land/my_act.xml
Android在不同的设备和不同的位置中选择了其中之一。
如何找到以编程方式选择的一个?
Android是否有任何API将这些布局返回给程序?
编辑:Graham Borland的解决方案在我在评论中提到的某些情况下存在问题。
假设我有一个在不同资源文件夹中具有三种不同布局的活动。例如:
layout-land/my_act.xml
layout-xlarge/my_act.xml
layout-xlarge-land/my_act.xml
Android在不同的设备和不同的位置中选择了其中之一。
如何找到以编程方式选择的一个?
Android是否有任何API将这些布局返回给程序?
编辑:Graham Borland的解决方案在我在评论中提到的某些情况下存在问题。
Answers:
您可以values-<config>
为每个受支持的配置创建目录。在这些目录中的每个目录中,创建一个strings.xml
具有单个selected_configuration
字符串的字符串,该字符串描述当前配置。在运行时,使用标准getString
方法获取字符串,该方法将为您进行配置解析,并为配置返回正确的字符串。这是未经测试的。
strings.xml
每个values-<config>
资源文件夹的所有内容,可以创建一个自定义文件,例如layout_type.xml
,然后仅将selected_configuration
其放入其中。
您可以android:tag
在每个不同资源文件中的视图上设置不同的属性,并使用运行时读回标记View.getTag()
。
例:
布局-xlarge-land / my_act.xml
<View
android:id="@+id/mainview"
android:tag="xlarge-landscape"
/>
layout-xlarge / my_act.xml
<View
android:id="@+id/mainview"
android:tag="xlarge-portrait"
/>
MyActivity.java
String tag = view.getTag();
if (tag.equals("xlarge-landscape") {
...
}
onCreate()
方法中获得标签时,它会给我标签的真实值,例如“ layout-xlarge-land”。但是,当我单击该页面上的按钮并使用该按钮findViewById()
并获取其标签时,其值为默认布局标签“ layout”。为什么?????
tabHost.addTab(myTabSpec);
代码行从“ layout-xlarge-land”更改为“ layout”?为什么???
TabHost
还会使用标记,因此您的用法可能会与它发生冲突。参见grepcode.com/file/repository.grepcode.com/java/ext/…–
您可以尝试重复这种算法“ Android如何找到最匹配的资源” -这非常简单,尤其是当您仅针对不同的屏幕使用不同的布局时。
Context.getResources().getConfiguration()
我的答案是从@Graham Borland实现的
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch(metrics.densityDpi){
case DisplayMetrics.DENSITY_LOW:
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("small-landscape") {
.....
}
}
else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("small-potrait") {
.....
}
}
break;
case DisplayMetrics.DENSITY_MEDIUM:
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("medium-landscape") {
.....
}
}
else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("medium-potrait") {
.....
}
}
break;
case DisplayMetrics.DENSITY_HIGH:
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("large-landscape") {
.....
}
}
else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
String tag = view.getTag();
if (tag.equals("large-potrait") {
.....
}
}
break;
}
这将适用于API lavel 4或更高版本。
onCreate()
方法中获得标签时,它会给我标签的真实值,例如“ layout-xlarge-land”。但是,当我单击该页面上的按钮并使用该按钮findViewById()
并获取其标签时,其值为默认布局标签“ layout”。为什么?????
tabHost.addTab(myTabSpec);
代码行从“ layout-xlarge-land”更改为“ layout”?为什么???
我假设您setContentView(int resID)
用来设置活动的内容。
方法1 (这是我的答案)
现在,在所有布局中,确保根视图始终具有正确的标记:
例:
layout-xlarge/main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:tag="xlarge-landscape"
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="@string/hello" />
</LinearLayout>
layout-small/main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:tag="small"
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="@string/hello" />
</LinearLayout>
现在让您的活动扩展此活动:
package shush.android.screendetection;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SkeletonActivity extends Activity {
protected String resourceType;
@Override
public void setContentView(int layoutResID) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(layoutResID, null);
resourceType = (String)view.getTag();
super.setContentView(view);
}
}
在这种情况下,您可以使用resourceType
来了解所使用的资源标识符。
方法2 (这是我的答案,但在发布之前我想到了更好的答案)
现在,在所有布局中,确保根视图始终具有正确的标记:
例:
layout-xlarge/main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:tag="xlarge-landscape"
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="@string/hello" />
</LinearLayout>
layout-small/main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:tag="small"
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="@string/hello" />
</LinearLayout>
现在让您的活动扩展此活动:
package shush.android.screendetection;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SkeletonActivity extends Activity {
@Override
public void setContentView(int layoutResID) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(layoutResID, null);
fix(view, view.getTag());
super.setContentView(view);
}
private void fix(View child, Object tag) {
if (child == null)
return;
if (child instanceof ViewGroup) {
fix((ViewGroup) child, tag);
}
else if (child != null) {
child.setTag(tag);
}
}
private void fix(ViewGroup parent, Object tag) {
for (int i = 0; i < parent.getChildCount(); i++) {
View child = parent.getChildAt(i);
if (child instanceof ViewGroup) {
fix((ViewGroup) child, tag);
} else {
fix(child, tag);
}
}
}
}
在这种情况下,层次结构中的所有视图都将具有相同的标记。
我不知道找到它的确切方法。但是我们可以用不同的方式找到它。
在所有布局中添加一个textview。(隐藏可见性)。相应地分配xlarge,land,xlarge-land等值。
在程序中,从textview获取值。我们可以以某种方式了解这种情况。
您可以从Resources
对象获取有关屏幕方向和大小的信息。从那里您可以了解所使用的布局。
getResources().getConfiguration().orientation;
-返回Configuration.ORIENTATION_PORTRAIT
或Configuration.ORIENTATION_LANDSCAPE
。
int size = getResources().getConfiguration().screenLayout;
-返回屏幕尺寸的掩码。您可以针对Small,Normal,Large,xLarge尺寸进行测试。例如:
if ((size & Configuration.SCREENLAYOUT_SIZE_XLARGE)==Configuration.SCREENLAYOUT_SIZE_XLARGE)
您的问题与此相同。如何获取布局xml文件路径?
您可以在xml中添加具有相应文件夹名称的隐藏文本视图。
TextView path = (TextView)findViewbyid(R.id.hiddentextview);
String s = path.gettext().tostring();
确保文本视图的所有ID均相同。
例
if your xml is in `normal-mdpi` in hidden textview hard code `normal-mdpi`
if your xml is in `large-mdpi` in hidden textview hard code `large-mdpi`