[React Native] Responsive Layouts P1

Responsive layout trong lập trinh font-end hiểu đơn giản là việc thiết kế giao diện phù hợp với nhiều kích thước thiết bị khác nhau và nhiều trạng thái khác nhau. Trong lập trình di động, việc thực hiện responsive layout cho nhiều thiết bị di động với nhiều thiết bị có kích thước và

Responsive layout trong lập trinh font-end hiểu đơn giản là việc thiết kế giao diện phù hợp với nhiều kích thước thiết bị khác nhau và nhiều trạng thái khác nhau. Trong lập trình di động, việc thực hiện responsive layout cho nhiều thiết bị di động với nhiều thiết bị có kích thước và tỉ lệ màn hình khác nhau là việc tương đối khó khăn với những người mới bắt đầu làm quen với responsive layout.

Trong phần 1 mình sẽ chia sẻ cách xử lý responsive layout đơn giản nhất trong trường hợp người dùng xoay thiết bị di động theo chiều ngang.

1. Đặt vấn đề

Đây là giao diện ứng dụng khi thiết bị ở trạng thái màn hình dọc:

Tiếp theo là giao diện khi thiết bị ở trạng thái màn hình ngang trước khi xử lý responsive:

Cuối cùng là giao diện thiết bị ở trạng thái màn hình ngang sau khi đã xử lý responsive:

Giả sử bạn là sử dụng ứng dụng, bạn sẽ muốn sử dụng giao diện ngang theo cách nào. Mình đã tham khảo và thấy rằng, đã số mọi người sẽ thích sử dụng giao diện sau khi đã xử lý responsive. Và điều này cũng được mình chứng bằng việc apple đã xử lý phần danh bạ, tin nhắn… trên các thiết bị iphone của mình theo cách này.

2. Ý tưởng

Để thực hiện việc thay đổi giao diện khi người dùng xoay màn hình thiết bị, chúng ta cần xử lý bắt được sự kiện liên quan đến thao tác này. Sau khi đã kiểm soát được các sự kiện thay đổi màn hình trên thiết bị, ta sẽ tiến hành điều chỉnh giao diện sao cho phù hợp với từng trạng thái.

3. Coding

Để bắt lắng nghe các sự kiện thay đổi trên màn hình, mình sẽ sử dụng sự kiện removeEventListener của Dimensions trong react-native

static removeEventListener(type, handler)

Việc này có thể cần sử dụng ở rất nhiều màn hình nên mình sẽ viết một custom hook để sử dụng cho việc này:

import {useEffect, useState} from 'react';
import {Dimensions} from 'react-native';
export const useOrientation = () => {
  const [screenInfo, setScreenInfo] = useState(Dimensions.get('screen'));
  useEffect(() => {
    const onChange = (res: any) => {
      setScreenInfo(res.screen);
    };
    Dimensions.addEventListener('change', onChange);
    return () => Dimensions.removeEventListener('change', onChange);
  }, []);
  return {
    ...screenInfo,
    isPortrait: screenInfo.height > screenInfo.width,
  };
};

Ở đây mình sẽ không giải thích custom hook quá sâu về khái niệm nhưng các bạn có thể hiểu custom hook trong trường hợp này sẽ trả về một object gồm các thông tin liên quan đến màn hình như sau:

isPortrait : true khi màn hình ở trạng thái dọc, và false khi màn hình ở trạng thái ngang.

Dựng giao diện:

<SafeAreaView
      style={[
        styles.container,
        {flexDirection: orientation.isPortrait ? 'column' : 'row'},
      ]}>
      <View
        style={[
          styles.buttonContainer,
          {
            flexDirection: orientation.isPortrait ? 'row' : 'column',
            justifyContent: orientation.isPortrait ? 'space-around' : 'center',
          },
        ]}>
        <TouchableOpacity style={styles.button}>
          <Text>Button1</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.button}>
          <Text>Button2</Text>
        </TouchableOpacity>
      </View>
      {!orientation.isPortrait ? (
        <View style={{backgroundColor: '#FFFFFF', height: '100%', width: 2}} />
      ) : null}
      <FlatList<Data>
        data={[
          {key: 'C'},
          {key: 'C++'},
          {key: 'Java'},
          {key: 'C#'},
          {key: 'Javascript'},
          {key: 'Ruby'},
          {key: 'Python'},
          {key: 'Golang'},
        ]}
        ItemSeparatorComponent={renderDivider}
        renderItem={renderItem}
      />
    </SafeAreaView>

Code style cho giao diện:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000000',
  },
  buttonContainer: {
    alignItems: 'center',
  },
  button: {
    height: 60,
    width: 140,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#FFFFFF',
    margin: 16,
  },
  item: {
    justifyContent: 'center',
    alignItems: 'center',
    height: 50,
  },
  divider: {
    height: 2,
    backgroundColor: '#FFFFFF',
    width: '100%',
  },
});

Chúng ta sẽ có 2 view chính cần sử lý đó là container(view tổng quát của màn hình) và buttonContainer( view hiển thị các button). Khi màn hình ở trạng thái dọc thì view sẽ ở trạng thái hiện thị theo “column” ngược lại khi màn hình ở trạng thái ngang thì view sẽ hiển thị theo ‘row’. Mục đích để khi màn hỉnh ở trạng thái ngang, các button sẽ được di chuyển qua trái và phần còn lại bên phải là danh sách các item.

Với buttonContainer view, khi màn hình ở trạng thái dọc sẽ hiện thị các button theo chiều ngang và ngược lại.

Và đây là kết quả responsive khi thay đổi trạng thái màn hình:

4. Kết luận

Như vậy trong phần 1 mình đã chia sẽ cách xử lý responsive layout khi người dùng thay đổi trạng thái màn hình.

Các bạn có thể tham khảo mã nguồn tại: https://github.com/ducgiangtrankma/ResponsiveLayouts.git

Trong phần tiếp theo mình sẽ chia sẽ cách để tạo một bộ size style theo kích thước màn hình khác nhau để phục vụ cho việc xử lý responsive layout. Hẹn gặp lại các bạn trong phần 2.

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ