浅谈Android布局在不同机型上的适配(包含GridView)
最近一个个人项目快要接近尾声了,不过又出现了一个比较麻烦的问题,就是在不同分辨率的手机上,布局往往并不是我以为的那样,以下面这个界面为例:
目前来看,界面布局没有什么问题,不过在写布局文件时,我都是按照自己手机的高度来写的。遇到更高的手机,显示出来是这样的:
可以想到,如果是更短的手机,那么必然会导致显示不全的问题,所以我们需要根据用户手机的高度来动态调整每一个控件的高度。
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)相关推荐
- 浅谈Android布局
在前面的博客中,小编介绍了Android的极光推送以及如何实现登录的一个小demo,对于xml布局页面,摆控件这块的内容,小编还不是很熟练,今天小编主要简单总结一下在Android中的布局,学习过An ...
- 高通android逆向分析,浅谈Android高通(Qualcomm)和联发科(MTK)平台
一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...
- 浅谈Android游戏开发基础和经验
Android游戏开发基础和经验是本文要介绍的内容,主要是来了解并学习Android游戏开发的内容实例,具体关于Android游戏开发内容的详解来看本文. 做一个类似俄罗斯方块的android游戏开发 ...
- 浅谈Android中的MVP与动态代理的结合
浅谈Android中的MVP与动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右.从最开始到现在经 ...
- 浅谈Android保护技术__代码混淆
浅谈Android保护技术__代码混淆 浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读 ...
- android fps 垂直同步,浅谈Android流畅度
原标题:浅谈Android流畅度 哈哈 讲个故事 白 1 流畅度 关于流畅度谷歌官方给出的解释为:running at a consistent 60 frames per second, witho ...
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
原文地址: http://blog.csdn.net/luoshengyang/article/details/6627260 在前面一篇文章浅谈Service Manager成为Android进程间 ...
- android分屏模式_浅谈 Android 7.0 多窗口分屏模式的实现
从 Android 7.0 开始,Google 推出了一个名为"多窗口模式"的新功能,也就是我们常说的"分屏模式".那么,这个功能有什么用呢?作为开发者,我们又 ...
- 浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解
浅谈Android onTouchEvent 与 onInterceptTouchEvent的区别详解 本篇文章小编为大家介绍,Android onTouchEvent 与 onInterceptTo ...
最新文章
- 自动化测试框架的隐藏小细节,你都知道么
- 李进良/丁守谦:希望TD-LTE成为4G的统一标准
- 分布式技术追踪 2018年第二十期
- JS实现的展开隐藏效果
- Metrics, tracing 和 logging 的关系
- 工作88:vue实现当前页面刷新
- jsp出现The import Xxx type is not resolved...
- mysql galera haproxy_安装配置Haproxy代理MySQL Galera集群
- 转easyui datagrid 前台分页的实现
- python logger_牛逼!python中的logging模块居然这么好用!
- 网络安全之等级保护问题集
- Android系统中的广播(Broadcast)机制简要介绍和学习计划 .
- 如何使用Aiseesoft iPhone Ringtone Maker for Mac在Mac上制作铃声
- python爬取教务系统_python 爬取 强智科技教务系统(湖南)
- 圆桌讨论:计算机视觉如何渗透你我的生活?|CCF-GAIR 2017
- 无人机通信与网络学习笔记
- 贝叶斯分类python代码_机器学习实战之朴素贝叶斯进行文档分类(Python 代码版)...
- 《因子投资 - 方法与实践》新书上市
- 弗雷德里克·特曼:硅谷之父、斯坦福大学前副校长——(转自新浪网)
- 网站挂马危害及其防御措施