浅谈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.AppBarLayout
        android:id="@+id/abl_education"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android: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">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <com.youth.banner.Banner
                    android:id="@+id/banner"
                    android:layout_width="match_parent"
                    android:layout_height="175.5dp">
                </com.youth.banner.Banner>

                <LinearLayout
                    android:id="@+id/info"
                    android:layout_width="match_parent"
                    android:layout_height="20dp"
                    android:layout_marginTop="5dp"
                    android:background="#fff"
                    android:orientation="horizontal">

                    <TextView
                        android: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.MyGridView
                    android: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>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="20dp"
                    android:layout_marginTop="5dp"
                    android:background="#fff"
                    android:orientation="horizontal">

                    <TextView
                        android: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.MyGridView
                    android: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">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="0dp">

        <ImageView
            android:id="@+id/iv_grid"
            android:layout_width="60dp"
            android:layout_height="79.375dp"/>

        <TextView
            android: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);
}

猜你喜欢

转载自blog.csdn.net/Cyril_KI/article/details/114490195