MultiType的简单使用

在开发的过程中我们需要实现一些UI效果图,如果UI界面比较简单,清晰,我们就按正常的思路写布局即可。但是如果面对比较复杂UI界面,我们还按正常的思路从上到下使用一些常用的控件,可能代码逻辑就会很复杂。另外如果后续迭代进行局部或者大范围的更改,可能会很头疼,看也得看半天。比如看下面的例子:

                         

上面两个图是比较复杂的,如果我们用RecyclerView也能实现或者ListView ,HorizontalScrollView等一些控件直接组合实现也不是不行,但是Type类型太多会导致代码比较复杂,不利于以后的维护。今天就给大家介绍一个很容易就能实现这种复杂的UI的框架MultiType。 

思路:就像ListView中可以有一种类型的ItemView,也可以有多种类型的ItemView,而MultiType也是可以存在很多个不同的Item布局。他俩的区别就是ListView中的各种类型的Item布局是直接写在ListView内部就行内部类一样,而MultiType的ItemView布局则是像插件一样注册到MutiType中,每一个ItemView(布局包括逻辑)之间相互独立的,每个ItemView只需要关心自己的布局对应着很么类型的数据,会有什么样的逻辑即可。下面就通过第一幅图来说说怎么使用:

 我们将UI分成5种类型的ItemView,然后各自去实现它。

1.写一个Bean类,即是第一个ItemView中的数据。

 再写一个MyBannerView0类继承ItemViewProvider (为了清晰,我将此Bean0写入对应MyBannerView0中)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="4dp"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/icon0"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/tv0"
        android:layout_width="wrap_content"
        android:textSize="14sp"
        android:layout_height="wrap_content"
        android:text="分类" />
</LinearLayout>
public class MyBannerView0 extends ItemViewProvider<MyBannerView0.Bean0, MyBannerView0.ViewHolder0> {


    @NonNull
    @Override
    protected ViewHolder0 onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {

        View view0 = inflater.inflate(R.layout.item_banner0, parent, false);

        return new ViewHolder0(view0);
    }

    @Override
    protected void onBindViewHolder(@NonNull ViewHolder0 holder, @NonNull Bean0 bean0) {
        holder.icon0.setImageResource(bean0.ResId);//图片
        holder.textView0.setText(bean0.names);//下面的APP名字
    }

    public class ViewHolder0 extends RecyclerView.ViewHolder {

        ImageView icon0;
        TextView textView0;

        public ViewHolder0(@NonNull View itemView) {
            super(itemView);
            icon0 = itemView.findViewById(R.id.icon0);
            textView0 = itemView.findViewById(R.id.tv0);
        }
    }

//数据源Bean
    public static class Bean0 {
       public int ResId;
        public String names;

        public Bean0(int resId, String names) {
            ResId = resId;
            this.names = names;
        }
    }


}

.仿照上面的写第二个item

<?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="160dp"
    android:orientation="vertical">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="180dp">

    </WebView>

</LinearLayout>
public class MyBannerView1 extends ItemViewProvider<MyBannerView1.Bean1, MyBannerView1.ViewHolder1> {


    @NonNull
    @Override
    protected ViewHolder1 onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
        View view1 = inflater.inflate(R.layout.item_banner1, parent, false);
        return new ViewHolder1(view1);
    }

    @Override
    protected void onBindViewHolder(@NonNull ViewHolder1 holder, @NonNull Bean1 bean1) {
       //这个我们视为WebView控件,可以远程控制其显示
        holder.webView.loadUrl(bean1.url);
    }

    public class ViewHolder1 extends RecyclerView.ViewHolder {

        WebView webView;

        public ViewHolder1(@NonNull View itemView) {
            super(itemView);
            webView = itemView.findViewById(R.id.webView);
            WebSettings webSettings = webView.getSettings();
            //支持缩放,默认为true。
            webSettings.setSupportZoom(false);
            //调整图片至适合webview的大小
            webSettings.setUseWideViewPort(true);
            // 缩放至屏幕的大小
            webSettings.setLoadWithOverviewMode(true);
            //设置默认编码
            webSettings.setDefaultTextEncodingName("utf-8");
            webSettings.setJavaScriptEnabled(true);
            webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();
            }
        });
        }
    }

    public static class Bean1 {

       public String url;

        public Bean1(String url) {
            this.url = url;
        }
    }

}

2.然后在Activity中注册这两个ItemView

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"

    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
    android:id="@+id/recycle"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>


</LinearLayout>

 

public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    MultiTypeAdapter multiTypeAdapter;
    Items items;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recycle); 
       //每一行最多可以显示12个Item
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 12);
       //根据实际情况,每一种类型的Item占据多少权重。比如第一行这种类型的最多有6个,每个占据的权重就是2
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {

            @Override
            public int getSpanSize(int i) {
                if (items.get(i) instanceof MyBannerView0.Bean0) {
                    return 12 / 6;   每个item占据2个权重
                } else if (items.get(i) instanceof MyBannerView1.Bean1) {
                    return 12 / 1;   每个item占据12权重

                } else if (items.get(i) instanceof MyEmptyBannerView.EmptyBean) {
                    return 12 / 1; 

                } else if (items.get(i) instanceof MyBannerView2.Bean2) {
                    return 12 / 1;
                } else if (items.get(i) instanceof MyBannerView3.Bean3) {
                    return 12 / 1;
                }
                return 12;
            }
        });
        //设置RecycleView
        recyclerView.setLayoutManager(gridLayoutManager);
        //类似于ArrayList<Object>
        items = new Items();
        //将每种类型的Item布局,注册到multiTypeAdapter 里面去
        multiTypeAdapter = new MultiTypeAdapter(items);
        multiTypeAdapter.register(MyBannerView0.Bean0.class, new MyBannerView0());
        multiTypeAdapter.register(MyBannerView1.Bean1.class, new MyBannerView1());
        multiTypeAdapter.register(ArrayList.class, new MyBannerView2());
        multiTypeAdapter.register(MyBannerView3.Bean3.class, new MyBannerView3());
        multiTypeAdapter.register(MyEmptyBannerView.EmptyBean.class, new MyEmptyBannerView());
        recyclerView.setAdapter(multiTypeAdapter);
        //请求数据,刷新数据。此时Adapter会根据item中的数据类型找到对应的布局并显示。
        requestData();

    }

    private void requestData() {
    //伪代码,模拟请求。
        items.clear();
        for (int i = 0; i < 6; i++) {
            items.add(new MyBannerView0.Bean0(R.mipmap.ic_launcher, "测试"));

        }
        items.add(new MyBannerView1.Bean1("http://www.baidu.com/"));
        items.add(new MyEmptyBannerView.EmptyBean(null));
        items.add(new MyEmptyBannerView.EmptyBean("热门应用"));
        ArrayList<MyBannerView2.Bean2> list = new ArrayList<>();
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "饿了么", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "腾讯视频", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "美团", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "腾讯QQ", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "微信", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "抖音", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "高德地图", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "百度外卖", ""));
        list.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "大众点评", ""));
        items.add(list);
        items.add(new MyEmptyBannerView.EmptyBean(null));
        items.add(new MyEmptyBannerView.EmptyBean("热门游戏"));
        ArrayList<MyBannerView2.Bean2> list1 = new ArrayList<>();
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "王者荣耀", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "皇室战争", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "炫舞", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "一道传世", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "三国群英传", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "火影忍者", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "穿越火线", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "英雄杀送", ""));
        list1.add(new MyBannerView2.Bean2(R.mipmap.ic_launcher, "使命召唤", ""));
        items.add(list1);
        items.add(new MyEmptyBannerView.EmptyBean(null));
        items.add(new MyEmptyBannerView.EmptyBean("长路漫漫,旅途相伴"));
        for (int i = 0; i < 15; i++) {
            items.add(new MyBannerView3.Bean3(R.mipmap.ic_launcher, "穿越火线" + i, "特别好玩的游戏" + i, ""));
        }
        multiTypeAdapter.notifyDataSetChanged();
    }
}

很简单就实现了这个效果:虽然丑,但是很直观。实际开发的时候这些图标啊  文字啊   以及WebView的链接啊 之类的都是接口返回的,链接不对或者打不开的做个默认设置就好。

 

 

 

总结:

优点:最大的优点就是MultiType可以实现各种不同类型布局组合成的复杂界面,每个BannerView之间是解耦的,像插件一样,Adapter会根据item的数据进行匹配对应的BannerView。  让开发者们可以灵活的添加,修改。

重点:

1.分析UI有几种类型的布局,并写出每一个BannerView

2.将BannerView注册到MutiTypeAdapter中去

3.如果每一行显示的个数不一样的,可以使用权重的思想处理。

 

 

 

         

 

 

 

 

 

 

 

 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值