最近一个个人项目快要接近尾声了,不过又出现了一个比较麻烦的问题,就是在不同分辨率的手机上,布局往往并不是我以为的那样,以下面这个界面为例:

  目前来看,界面布局没有什么问题,不过在写布局文件时,我都是按照自己手机的高度来写的。遇到更高的手机,显示出来是这样的:

  可以想到,如果是更短的手机,那么必然会导致显示不全的问题,所以我们需要根据用户手机的高度来动态调整每一个控件的高度。

1.分析xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/abl_education"android:layout_width="match_parent"android:layout_height="match_parent"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/full_match"android:layout_width="match_parent"android:layout_height="match_parent"app:contentScrim="@color/main_color"app:layout_scrollFlags="scroll|exitUntilCollapsed"app:statusBarScrim="@android:color/transparent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.youth.banner.Bannerandroid:id="@+id/banner"android:layout_width="match_parent"android:layout_height="175.5dp"></com.youth.banner.Banner><LinearLayoutandroid:id="@+id/info"android:layout_width="match_parent"android:layout_height="20dp"android:layout_marginTop="5dp"android:background="#fff"android:orientation="horizontal"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:text="个人教务"android:textColor="#000000"android:textSize="14sp"/></LinearLayout><com.example.NCEPU.Utils.MyGridViewandroid:id="@+id/gv_education"android:layout_width="match_parent"android:layout_height="204.75dp"android:layout_marginTop="5dp"android:background="#fff"android:gravity="center"android:numColumns="4"android:verticalSpacing="0dp"android:scrollbars="none"></com.example.NCEPU.Utils.MyGridView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="20dp"android:layout_marginTop="5dp"android:background="#fff"android:orientation="horizontal"><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:text="数据可视化"android:textColor="#000000"android:textSize="14sp" /></LinearLayout><com.example.NCEPU.Utils.MyGridViewandroid:id="@+id/gv_vision"android:layout_width="match_parent"android:layout_height="204.75dp"android:layout_marginTop="5dp"android:background="#fff"android:gravity="center"android:numColumns="4"android:scrollbars="none"></com.example.NCEPU.Utils.MyGridView></LinearLayout></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout>
</LinearLayout>

  布局总体来讲是一个LinearLayout,最上方一个Banner,然后连续两个TextView+GridView,这是一个Fragment界面,最下面是ViewPager+Fragment+RadioButton实现的底部菜单栏,也占有一定高度。关于菜单栏的实现请见:
安卓:ViewPager+Fragment+RadioButton实现底部菜单栏滑动切换

  注意:要想界面在不同机型上适配,在布局文件中一定要尽量少使用padding和margin属性,这会让情况变得很复杂。

  最开始的xml文件中充斥着很多padding和margin,后面经过修改,我只保留了两个margin,即两个TextView(个人教务和数据可视化)上下各有5dp的间距。

  那么情况就很明显了:

屏幕高度=上方状态栏高度 + Banner高度 + 5dp + 20dp的TextView + 5dp
+ GridView + 5dp + 20dp的TextView + 5dp + GridView + 50dp的一组RadioButton。

2.获取屏幕高度:

WindowManager manager = this.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int width = outMetrics.widthPixels;
int height = outMetrics.heightPixels;
width = px2dip(this, width); //360dp
height = px2dip(this, height); //720dp

  其中像素px转dp方法px2dip:

public static int px2dip(Context context, float pxValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);
}

  最终算出屏幕高720dp,宽360dp。

3.获取上方状态栏高度:

public int getStatusBarHeight() {Resources resources = this.getResources();int resourceId = resources.getIdentifier("status_bar_height","dimen","android");int height = resources.getDimensionPixelSize(resourceId);return px2dip(this, height);  //24dp}

  上方状态栏高度为24dp。
  于是最终得到除了状态栏和下方RadioButton之外的高度:

int pagerHeight = height - status_bar_height - 50;

  然后我们将其写入一个SharedPreferences文件:

sharedPreferences = getSharedPreferences("user_info", Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
editor.putInt("pager", pagerHeight);
editor.commit();

  最终这个pager就是我们放置一个Banner + 两个GridView + 两个TextView的地方。

4.动态生成高度

  在QueryFragment的onCreateView方法中,我们需要来动态设置高度,在这里我把最上方轮播图与下方两个GriView的高度比定为6:7:7,即:

private void setHeight() {SharedPreferences sharedPreferences = getContext().getSharedPreferences("user_info", Context.MODE_PRIVATE);float pagerHeight = sharedPreferences.getInt("pager", StudentMainActivity.pagerHeight);pagerHeight -= 60;LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) banner.getLayoutParams();linearParams.height = dip2px(getContext(), pagerHeight / 20 * 6);banner.setLayoutParams(linearParams);linearParams = (LinearLayout.LayoutParams) eduGridView.getLayoutParams();linearParams.height = dip2px(getContext(), pagerHeight / 20 * 7);eduGridView.setLayoutParams(linearParams);linearParams = (LinearLayout.LayoutParams) visionGridView.getLayoutParams();linearParams.height = dip2px(getContext(), pagerHeight / 20 * 7);visionGridView.setLayoutParams(linearParams);
}

  减去的那个60dp就是两个TextView以及四个margin的高度,当然也可以动态设置两个TextView的高度,不过我限制死了,就让它高20dp。

5.GridView的Adapter文件修改

  GridView的使用需要Adapter文件的配合,在适配器文件中我们设置每一个item,在这里,item就是上方一个ImageView,下方一个TextView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:orientation="vertical"android:padding="0dp"><ImageViewandroid:id="@+id/iv_grid"android:layout_width="60dp"android:layout_height="79.375dp"/><TextViewandroid:id="@+id/tv_grid"android:layout_width="wrap_content"android:layout_height="20dp"android:layout_marginTop="3dp"android:gravity="center"android:text=""/></LinearLayout>
</LinearLayout>

  于是乎在适配器文件里我们也要动态设置每一个item的高度,因为每一个GridView都有两排,所以一个GridView的高度就为:

height = (ImageView + 3dp的margin + TextView高度) * 2

  这里TextView的高度也像前面一样,我都写死为20dp,而GridView的高度前面已经算过了:

float gridViewHeight = pagerHeight / 20 * 7;

  所以最终ImageView的高度为:

(gridViewHeight - 46) / 2

  所以最终我们这样设置:

@Override
public View getView(int position, View convertView, ViewGroup parent) {View view = LayoutInflater.from(context).inflate(R.layout.item_grid, null);SharedPreferences sharedPreferences = context.getSharedPreferences("user_info", Context.MODE_PRIVATE);pagerHeight -= 60;float gridViewHeight = pagerHeight / 20 * 7;ImageView iv = view.findViewById(R.id.iv_grid);TextView tv = view.findViewById(R.id.tv_grid);LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) iv.getLayoutParams();linearParams.height = dip2px(context, (gridViewHeight - 46) / 2);iv.setLayoutParams(linearParams);iv.setImageResource(images[position]);tv.setText(names[position]);return view;
}

  核心代码为:

LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams) iv.getLayoutParams();
linearParams.height = dip2px(context, (gridViewHeight - 46) / 2);
iv.setLayoutParams(linearParams);

  这里需要注意:LinearLayout.LayoutParams在设置高度时,需要将其转为像素,所以需要用到dip2px:

public static int dip2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);
}

浅谈Android布局在不同机型上的适配(包含GridView)相关推荐

  1. 浅谈Android布局

    在前面的博客中,小编介绍了Android的极光推送以及如何实现登录的一个小demo,对于xml布局页面,摆控件这块的内容,小编还不是很熟练,今天小编主要简单总结一下在Android中的布局,学习过An ...

  2. 高通android逆向分析,浅谈Android高通(Qualcomm)和联发科(MTK)平台

    一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...

  3. 浅谈Android游戏开发基础和经验

    Android游戏开发基础和经验是本文要介绍的内容,主要是来了解并学习Android游戏开发的内容实例,具体关于Android游戏开发内容的详解来看本文. 做一个类似俄罗斯方块的android游戏开发 ...

  4. 浅谈Android中的MVP与动态代理的结合

    浅谈Android中的MVP与动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右.从最开始到现在经 ...

  5. 浅谈Android保护技术__代码混淆

    浅谈Android保护技术__代码混淆 浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读 ...

  6. android fps 垂直同步,浅谈Android流畅度

    原标题:浅谈Android流畅度 哈哈 讲个故事 白 1 流畅度 关于流畅度谷歌官方给出的解释为:running at a consistent 60 frames per second, witho ...

  7. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...

  8. android分屏模式_浅谈 Android 7.0 多窗口分屏模式的实现

    从 Android 7.0 开始,Google 推出了一个名为"多窗口模式"的新功能,也就是我们常说的"分屏模式".那么,这个功能有什么用呢?作为开发者,我们又 ...

  9. 浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解

    浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解 本篇文章小编为大家介绍,Android onTouchEvent 与 onInterceptTo ...

最新文章

  1. 自动化测试框架的隐藏小细节,你都知道么
  2. 李进良/丁守谦:希望TD-LTE成为4G的统一标准
  3. 分布式技术追踪 2018年第二十期
  4. JS实现的展开隐藏效果
  5. Metrics, tracing 和 logging 的关系
  6. 工作88:vue实现当前页面刷新
  7. jsp出现The import Xxx type is not resolved...
  8. mysql galera haproxy_安装配置Haproxy代理MySQL Galera集群
  9. 转easyui datagrid 前台分页的实现
  10. python logger_牛逼!python中的logging模块居然这么好用!
  11. 网络安全之等级保护问题集
  12. Android系统中的广播(Broadcast)机制简要介绍和学习计划 .
  13. 如何使用Aiseesoft iPhone Ringtone Maker for Mac在Mac上制作铃声
  14. python爬取教务系统_python 爬取 强智科技教务系统(湖南)
  15. 圆桌讨论:计算机视觉如何渗透你我的生活?|CCF-GAIR 2017
  16. 无人机通信与网络学习笔记
  17. 贝叶斯分类python代码_机器学习实战之朴素贝叶斯进行文档分类(Python 代码版)...
  18. 《因子投资 - 方法与实践》新书上市
  19. 弗雷德里克·特曼:硅谷之父、斯坦福大学前副校长——(转自新浪网)
  20. 网站挂马危害及其防御措施

热门文章

  1. A7139无线驱动调试
  2. 【浅度渣文】Jackson之jackson-core
  3. 计算机中64位和32位什么意思?有什么区别?
  4. 关于新增dnsmasq --help的option选项
  5. P1000刷机知识+获取ROOT+HDVS_ROM快速刷机教程 by fox
  6. Android:会呼吸的悬浮气泡
  7. Springboot后台HTML/富文本转图片
  8. Android开发 WebSocket
  9. matlab信号系统实验报告,信号与系统 MATLAB实验报告
  10. 邦纳LTF12KC2LDQ激光传感器