美文网首页
iOS UITableView和Android Recycler

iOS UITableView和Android Recycler

作者: Ello_Orld | 来源:发表于2020-02-09 16:45 被阅读0次
  • UITableView是iOS中使用很广泛的一种列表控件,类似Android中的RecyclerView(ListView暂不考虑了),继承自UIScrollView,利用复用机制,实现高性能的滑动

1. 最基本的使用

eg:数据源是一个数组,内容如下:

    String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21"};

显示一个简单的列表

  • Android实现
    首先添加依赖:
implementation 'androidx.recyclerview:recyclerview:1.1.0'

添加Activity主布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

添加item_view

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/tv_item"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:padding="10dp"
    android:textColor="@android:color/black"
    android:textSize="16sp"
    tools:text="123" />

在MainActivity中处理代码(Adapter就不分开写了)

package com.dxl.recyclerviewdemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;

    String[] data = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21"};
    private MyAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = findViewById(R.id.recycler_view);
        mAdapter = new MyAdapter(this, Arrays.asList(data));
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

    class MyAdapter extends RecyclerView.Adapter<MyViewHolder>{

        private List<String> dataList;
        private Context mContext;

        public MyAdapter(Context context, List<String> list) {
            this.dataList = list;
            this.mContext = context;
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext).inflate(R.layout.view_item, parent, false);
            return new MyViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            holder.mTextView.setText(dataList.get(position));
        }

        @Override
        public int getItemCount() {
            return dataList.size();
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView mTextView;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            mTextView = itemView.findViewById(R.id.tv_item);
        }
    }
}

实现效果:


Android
  • iOS实现
    iOS实现起来简单一些,需要的代码量比较小。

创建一个SingleViewApp
打开Main.storyboard,拖拽一个TableView到主界面,调整大小
属性面板里调整Prototype Cells为1,这时左侧布局中会出现一个cell。
点击cell,调整cell属性,Style设置为Basic,添加一个Identifier


image.png

拖动tableView到viewController实现数据源和代理

//
//  ViewController.m
//  testTableView
//
//  Created by dxl on 2020/2/9.
//  Copyright © 2020 dxl. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>

@property(strong, nonatomic)NSArray *dataArray;

@end

@implementation ViewController

- (NSArray *)dataArray {
    if (!_dataArray) {
        _dataArray = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", @"13", @"14", @"15", @"16", @"17", @"18", @"19", @"20", @"21", nil];
    }
    return _dataArray;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"item_cell"];
    cell.textLabel.text = self.dataArray[indexPath.row];
    return cell;
}

- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataArray.count;
}

@end

运行效果:


Simulator Screen Shot - iPhone 11 Pro Max - 2020-02-09 at 16.44.56.png

2. 分割线

Android RecyclerView默认不带分割线属性,需要自己定义。
1)可以使用默认的分割线

//添加自带默认分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));

如果自带的分割线不能满足条件,可以在上述基础上添加一个drawable。
比如定义一个drawable,divider_shape.xml,定义分割线大小为1px,颜色为灰色

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size
        android:width="1px"
        android:height="1px" />
    <solid android:color="@android:color/darker_gray"/>

</shape>

添加分割线的代码修改以下:

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
dividerItemDecoration.setDrawable(ContextCompat.getDrawable(this, R.drawable.shape_divider));
mRecyclerView.addItemDecoration(dividerItemDecoration);

看一下效果:


image.png

如果分割线比较复杂,上面的shape不能满足要求,就需要自定义,我们还是可以自己去添加分割线,RecyclerView提供了一个抽象类ItemDecoration,它是item的装饰类。


iOS UITableView添加分割线
打开storyboard,调整tableview属性,


image.png

,设置分割线样式和颜色


Simulator Screen Shot - iPhone 11 Pro Max - 2020-02-09 at 17.55.34.png

iOS UITableView cell 四种样式:

UITableViewCellStyleDefault,    // Simple cell with text label and optional image view
UITableViewCellStyleValue1,     // Left aligned label on left and right aligned label on right with blue text (Used in Settings)
UITableViewCellStyleValue2,     // Right aligned label on left with blue text and left aligned label on right (Used in Phone/Contacts)
UITableViewCellStyleSubtitle    // Left aligned label on top and left aligned label on bottom with gray text (Used in iPod)

分别对应storyboard中的四种属性:
Basic,LeftDetail,RightDetail,Subtitle

3. header和footer

iOS中UITableView有两种方式设置header,一种是纯文本,一种是自定义view。

  • 纯文本:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    return @"header";
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 50.0f;
}

运行如下:


image.png

如果header不是纯文本,或者自带样式不能满足,可以重写下列方法自定义header显示的view

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 100.0f;
}


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, screenWidth, 100)];
    headerView.backgroundColor = [UIColor greenColor];

    UILabel *label = [[UILabel alloc]initWithFrame:headerView.frame];
    label.text = @"自定义视图header";
    label.textAlignment = NSTextAlignmentCenter;
    [headerView addSubview:label];
    return headerView;
}

运行效果如下:


image.png

.
注意自定义view 的高度受viewForHeaderInSection的约束,如果不重写viewForHeaderInSection的话,系统会有一个默认高度,但不是自定义view 的高度。

footer同理。

Android RecyclerView
遗憾的是,RecyclerView原生没有提供headerView和footerView等相关的方法,处理的方法只能是把headerView和footerView作为一种viewType在adapter中进行处理。
还是以刚才iOS达到的效果为例:
修改adapter


import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private List<String> dataList;
    private Context mContext;

    public static final int TYPE_HEADER = 0;
    public static final int TYPE_DEFAULT = 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({TYPE_HEADER, TYPE_DEFAULT})
    public @interface ItemType {
    }

    public MyAdapter(Context context, List<String> list) {
        this.dataList = new ArrayList<>(list);
        this.dataList.add(0, "");
        this.mContext = context;
    }

    @Override
    public @ItemType
    int getItemViewType(int position) {
        return position == 0 ? TYPE_HEADER : TYPE_DEFAULT;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, @ItemType int viewType) {
        View view;
        if (viewType == TYPE_HEADER) {
            view = new TextView(mContext);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100);
            ((TextView) view).setText("自定义header");
            ((TextView) view).setTextColor(Color.BLACK);
            view.setLayoutParams(layoutParams);
            view.setBackgroundColor(Color.GREEN);
            ((TextView) view).setGravity(Gravity.CENTER);
        } else {
            view = LayoutInflater.from(mContext).inflate(R.layout.view_item, parent, false);
        }
        return new MyViewHolder(view, viewType);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        int viewType = getItemViewType(position);
        if (viewType == TYPE_DEFAULT) {
            holder.mTextView.setText(dataList.get(position));
        }
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView mTextView;

        public MyViewHolder(@NonNull View itemView, @ItemType int itemType) {
            super(itemView);
            mTextView = itemView.findViewById(R.id.tv_item);
        }
    }
}

运行查看效果:


image.png

4. 点击事件:

UITableView点击事件处理比较简单:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"当前点击的内容是%@", self.dataArray[indexPath.row]);
}

安卓就麻烦些了,因为RecyclerView原生没有提供item点击事件:
修改adapter:

package com.dxl.recyclerviewdemo;

import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private List<String> dataList;
    private Context mContext;

    private ListenerWithPosition.OnItemPositionClickListener mListener;

    public void setListener(ListenerWithPosition.OnItemPositionClickListener listener) {
        mListener = listener;
    }

    public static final int TYPE_HEADER = 0;
    public static final int TYPE_DEFAULT = 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({TYPE_HEADER, TYPE_DEFAULT})
    public @interface ItemType {
    }

    public MyAdapter(Context context, List<String> list) {
        this.dataList = new ArrayList<>(list);
        this.dataList.add(0, "");
        this.mContext = context;
    }

    @Override
    public @ItemType
    int getItemViewType(int position) {
        return position == 0 ? TYPE_HEADER : TYPE_DEFAULT;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, @ItemType int viewType) {
        View view;
        if (viewType == TYPE_HEADER) {
            view = new TextView(mContext);
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100);
            ((TextView) view).setText("自定义header");
            ((TextView) view).setTextColor(Color.BLACK);
            view.setLayoutParams(layoutParams);
            view.setBackgroundColor(Color.GREEN);
            ((TextView) view).setGravity(Gravity.CENTER);
        } else {
            view = LayoutInflater.from(mContext).inflate(R.layout.view_item, parent, false);
        }
        return new MyViewHolder(view, viewType);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        if (mListener != null) {
            holder.itemView.setOnClickListener(new ListenerWithPosition(mListener, position));
        }
        int viewType = getItemViewType(position);
        if (viewType == TYPE_DEFAULT) {
            holder.mTextView.setText(dataList.get(position));
        }
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView mTextView;

        public MyViewHolder(@NonNull View itemView, @ItemType int itemType) {
            super(itemView);
            mTextView = itemView.findViewById(R.id.tv_item);
        }
    }

    public static class ListenerWithPosition implements View.OnClickListener {

        private OnItemPositionClickListener mClickListener;
        private int mPosition;

        public ListenerWithPosition(OnItemPositionClickListener clickListener, int position) {
            mClickListener = clickListener;
            mPosition = position;
        }

        interface OnItemPositionClickListener {
            void onClick(View v, int position);
        }

        @Override
        public void onClick(View v) {
            if (mClickListener != null) {
                mClickListener.onClick(v, mPosition);
            }
        }
    }
}

在MAinActivity中设置点击事件:

mAdapter.setListener(new MyAdapter.ListenerWithPosition.OnItemPositionClickListener() {
            @Override
            public void onClick(View v, int position) {
                Toast.makeText(MainActivity.this, data[position - 1], Toast.LENGTH_LONG).show();
            }
        });

相关文章

网友评论

      本文标题:iOS UITableView和Android Recycler

      本文链接:https://www.haomeiwen.com/subject/hrfnxhtx.html