大项目布局分析 | 青训营笔记

123 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的的第32天

作者: Eric0202

前言:

大作业是写一个简单版的抖音,根据团队安排, 我个人主要是写 《我的》页面, 那么久来分析一下抖音 《我的》页面的布局画法吧。

正文:

1. 总体布局

Feishu20220823-135554.png

这是一个需要滑动的界面,明显下滑后应该从作品上方分开,作品等四个tab保留在顶部, 其他部分隐藏,因此分为两个部分。首先分析下下面的作品部分, 比较简单。

2. 作品布局

tab

image-20220823141422589.png

这里是一个tabLayout

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tabs"
    android:layout_width="match_parent"
    android:layout_height="50dp" />

定义一个宽度matchparent的tab,只需要写死高度,定好id,内容可以之后在java代码中通过id加上

viewpager

image-20220823151757631.png

这一部分就是viewpager 里面加载recyclerview和adapter,item实现

这里用的是recyclerview,一般也可以用gridview来写,简单的在xml里面写一个gridview, 然后将宽度占满,注意一定不要忘记id, 通过id和adapter向里面填充数据

里面的每一个item的布局,首先是背景的图片,然后是一个播放按钮和一个观看数字,也可以在左上角放一个 《置顶》的标签。

最简单的做法我觉得应该用constraitlayout, constraintlayout是谷歌比较推荐的做法,优点是在画复杂布局时避免的layout嵌套。

做法:

  1. itemlayout的imageview填满整个布局,constraint个四个方向都和parent对齐

  2. 一个小的imageview,start to parent start, bottom to parent buttom, 然后写上id

    这里用start而不是left,left依然可以生效,但是现在一般都建议用start了

  3. 一个小的textview,字体白色,start to 之前的小image 的 end, bottom to parent bottom

完成。

对于image的加载, 我觉得glide是要明显优于系统自带src的, 当图片稍多的时候,系统src的方法就会明显加载卡顿,glide依然非常迅速

layout:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

recyclerview:

public class MyRecyclerView extends RecyclerView {

    public MyRecyclerView(@NonNull Context context) {
        super(context);
    }

    public MyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    // 记录上一次滑动的坐标
    private int mLastX,mLastY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int x = (int)ev.getX();
        int y = (int)ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                getParent().requestDisallowInterceptTouchEvent(true);
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            }
            case MotionEvent.ACTION_UP:{
                break;
            }
            default:
                break;
        }
        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(ev);
    }

}

fragment内的layout:

<com.byteteam.douyin.widget.MyRecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

item:

item的代码就有点多,避免代码远超文字, 就不放出来了。