본문 바로가기
앱인벤터/실전 앱

앱인벤터 채팅앱 만들기 #2 (채팅 화면 구성)

by 이지이지(EGEasy) 2021. 11. 26.

안녕하세요. 이지이지입니다.

이번 포스팅에서는 지난 시간에 이어 앱인벤터로 채팅앱 만들기를 완성하도록 하겠습니다.

 

실제 채팅이 이루어지고 메시지가 오고가는 화면(Screen2)을 구성합니다.

지난 포스팅과 같은 소스파일을 다시 올려드리니 참고하시기 바랍니다.

 

EG_CHAT.aia
0.01MB

 

 

    화면 구성

Screen2에 대한 화면 구성입니다.

 

Screen2 화면 구성

 

Screen2에서 핵심이 되는 것은 FirebaseDB(firebase_Chat)ListView 컴포넌트입니다.

 

FirebaseDB의 속성(Properties) 설정은 이전 1번 포스팅을 참고하시고,

ListView를 제외한 컴포넌트들의 속성은 디자인적인 요소일 뿐 기능에는 큰 영향을 미치지 않으므로 소스파일을 참고하면 되겠습니다.

 

이번 포스팅에서는 예제 앱에서 사용된 ListView의 속성에 대해서만 설명드리도록 하겠습니다. 

 

ListView 속성

 

채팅앱 예제를 위해서는 특히 빨간색 상자로 된 부분의 값을 잘 따라 입력해주시구요.

리스트뷰에 대한 전반적인 설명은 앱인벤터 홈페이지의 문서를 인용해서 설명드리겠습니다.

 

 

 

 

 

 

 

 

 

 

리스트뷰의 레이아웃은 총 6가지로 구성할 수 있습니다.

 

1. 예전 방식의 텍스트만 있는 리스트뷰

- ElementsFromString 속성을 통해 데이터를 입력 (속성창 또는 블록으로 설정 가능)

예전 방식의 리스트뷰

 

2. 새로운 방식의 리스트뷰

- ListDataListViewLayout 속성을 통해 데이터를 입력

- 데이터를 ListData의 속성이 아닌 블록을 통해 구성할 때는 Set "컴포넌트 이름".Elements to 블록을 이용

(더 자세한 사항은 아래 블록 코딩 참고)

- ListViewLayout속성창에서만 설정 가능

 

2-1. ListViewLayout의 속성이 MainText인 경우

MainText로 속성이 지정된 경우

 

2-2. ListViewLayout의 속성이 Main, DetailText(Orientation: vertical)인 경우

Main,DetailText(Orientation: vertical)로 속성이 지정된 경우

 

2-3. ListViewLayout의 속성이 Main, DetailText(Orientation: horizontal)인 경우

Main,DetailText(Orientation: horizontal)로 속성이 지정된 경우

 

2-4. ListViewLayout의 속성이 Image, MainText인 경우

Image, MainText로 속성이 지정된 경우

 

2-5. ListViewLayout의 속성이 Image, MainText, DetailText인 경우

Image, MainText, DetailText로 속성이 지정된 경우

 

 

※ 모든 경우에 있어 MainText필수값이며, ImageDetailText선택사항입니다.

 

 

    블록 코딩

 

다음 이미지는 Screen2의 전체 블록 코딩입니다.

 

전체 블록 코딩

 


 

먼저 Screen2가 처음 나타날 때 실행되는 블록입니다.

 

Screen2가 처음 실행되었을 때 실행되는 블록

 

① 변수 my_nickname을 만들고 값으로 공백을 저장해둡니다.

initialize global 변수명 to 블록은 항상 화면이 처음 실행될 때 함께 실행됩니다.

이해를 돕기 위해 그 변수가 처음 사용되는 블록이 있을 때 함께 설명합니다.

 

② Screen_Chat가 처음 실행되었을 때

 

③ 변수 my_nickname에 TinyDB1에서 myNickname 태그에 저장되어 있던 값을 가져와 저장합니다.

→ TinyDB1의 myNickname은 Screen1에서 사용자가 입력한 닉네임입니다. (채팅앱 1편 참고)

→ 굳이 또 다른 변수에 TinyDB1의 값을 저장하는 것은 코드의 간결함 때문입니다.

 

④ firebase_Chat의 ProjectBucket을 Chatroom/get start value로 지정합니다.

→ get start value는 Screen1에서 넘어 온 값을 받는 것입니다. 

→ Screen1에서는 사용자가 입력한 채팅방의 이름을 넘겨주도록 하였습니다. (채팅앱 1편 참고)

→ Screen1에서 사용자가 입력한 채팅방의 이름이 CHAT_1이었다면, ProjectBucket은 ChatRoom/CHAT_1이 됩니다.

 

⑤ 파이어베이스 Realtime Database에 tag는 사용자의 닉네임으로, 그 값으로는 빈 리스트를 저장합니다.

→ ProjectBucket이 ChatRoom/CHAT_1이었으므로 ChatRoom/CHAT_1/닉네임: "[ ]" 이런 식으로 저장이 되는 것입니다.

이 역시 채팅앱 1편을 참고하면 되겠습니다.

 

※ 다음 이미지는 채팅방 이름이 "CHAT_1"이고, 사용자의 닉네임이 "김유신"이며, 아직 채팅 메시지를 주고 받지 않았을 경우의 데이터베이스 화면입니다.

 

처음 채팅방이 개설되었을 때의 데이터베이스 구조

 

⑥ 사용자의 편의를 위해 채팅 메시지 입력창(txt_Message)의 커서가 깜빡이도록 설정합니다.

 

 


 

다음은 [전송] 버튼(btn_send)을 클릭했을 때 실행되는 블록입니다.

 

[전송] 버튼을 클릭했을 때 실행되는 블록

 

① [전송] 버튼을 클릭했을 때

 

② 사용자가 입력한 메시지(txt_Message.Text)가 공백이 아니라면, 

→ 사용자가 실수로 아무런 메시지도 입력하지 않은 채 [전송] 버튼을 누르는 경우도 있기 때문에 조건을 걸어 둔 것입니다.

 

③ Realtime Database에서 (ProjectBucket으로 지정해 둔 경로에서) 변수 my_nickname으로 된 tag의 값(리스트 형식, 위의 블록 ⑤에서 빈 리스트로 만들어 두었음.) 에 사용자가 입력한 메시지(txt_Message.Text)를 리스트의 가장 끝에 추가합니다.

 

※ 다음 이미지는 사용자의 닉네임이 "김유신"이고, 입력한 메시지가 "안녕!"일 경우의 데이터베이스 구조입니다.

 

메시지가 입력된 데이터베이스 구조

 

④ [전송] 버튼을 눌렀다는 것은 메시지 입력이 끝났다는 것이므로 키보드를 숨깁니다.

 

⑤ 사용자가 새로운 메시지를 작성하기 쉽도록, txt_Message.Text를 공백으로 설정합니다.

→ 기존에 입력되어 있던 내용을 지우는 역할입니다.

 

 


 

채팅앱은 실시간으로 메시지가 오고가는 것이라 메시지를 저장하고 있는 데이터베이스 역시 실시간으로 변경됩니다.

따라서 데이터베이스의 내용이 변할 때마다 앱에서도 변화를 주어야 합니다.

 

다음 블록은 데이터베이스의 데이터가 변할 때마다 실행되는 블록과 이에 필요한 변수들에 대한 블록입니다.

 

데이터가 변경되었을 때 실행되는 블록

 

① 채팅 메시지를 저장할 리스트 형식의 변수 lv_list를 빈 리스트로 만들어둡니다. (Screen2가 처음 나타날 때 실행됨)

리스트뷰의 데이터는 항상 리스트 형식으로 더해주어야 해서 리스트 형식으로 만들어 두는 것입니다.

 

② 채팅에 참가한 사람들을 저장해 둘 변수 users를 빈 리스트로 만들어둡니다.

→ 채팅창 상단에 참가자 닉네임과 참가자 수를 표시하기 위한 것입니다.

 

③ 데이터베이스에 데이터가 변경되었을 때,

→ 채팅앱에서 데이터베이스의 데이터가 변경되는 경우는 세 가지 경우가 있습니다.

 

1. 채팅방을 개설할 경우: 채팅방 이름과 비밀번호, 자신의 닉네임과 빈 리스트가 생성됩니다.

2. 상대방이 채팅방에 입장할 경우: 상대방 닉네임과 빈 리스트가 생성됩니다.

3. 채팅 메시지를 주고 받을 경우: 닉네임으로 된 tag의 값(리스트 형식) 맨 뒤에 메시지가 추가됩니다.

 

 

 

 

④ 만약 데이터가 변경된 것의 tag가 변수 users에 포함되어 있지 않고, tag가 "password"가 아니라면

→ 참여한 사용자의 닉네임이 변수 users에 포함되어 있지 않다는 의미입니다.

 

위에서 보여드렸던 데이터베이스 구조로 설명하자면

 

데이터베이스 구조의 예

 

Screen2가 처음 실행되었을 때 ProjectBucket을 ChatRoom/CHAT_1으로 설정해 두었습니다.

tag는 ProjectBucket의 바로 아래 하위수준 항목이 되므로, password, 김유신, 이순신이 tag가 되는 것입니다.

 

⑤ 변수 users에 데이터베이스에서 변경된(추가된) tag를 추가합니다.

→ 사용자의 닉네임을 추가하게 됩니다.

 

⑥ 채팅창 위에 나타나는 참여자 정보 레이블(lbl_Users)의 텍스트에 참여자 정보를 표시합니다.

→ 김유신, 이순신 (2) 처럼 나타납니다.

→ join items using separator 블록은 리스트에 있는 항목을 구분자로 연결하여 텍스트 형식으로 변환합니다.

=> 리스트 형식의 변수 users ["김유신", "이순신"]를 텍스트 형식에 바로 사용할 수 없으므로 변환시키는 것입니다.

 

⑦ 만약 변경된 데이터의 tag가 "password"가 아니라면

→ tag는 사용자 닉네임이 될 것입니다.

 

⑧ 만약 가져온 값이 빈 리스트가 아니라면

→ 빈 리스트는 사용자가 처음 참여할 때 만들어 지는 것이라, 빈 리스트가 아니라는 것은 메시지가 입력되었음을 알려줍니다.

 

⑨~⑩ 리스트 형식의 변수 lv_list에 항목을 추가합니다.

call 리스트뷰 이름.CreateElement는 새로운 레이아웃 형식의 리스트뷰에 항목을 추가할 때 사용하는 블록입니다.

 

- mainText: 예제 앱에서는 사용자 닉네임을 mainText로 사용할 것이라 tag로 정합니다.

 

- detailText: 추가할 메시지 내용을 가장 마지막에 추가된 내용으로 합니다.

→ 위에서도 몇 번 언급했지만 tag는 사용자 닉네임, 이 tag에 대응되는 값(메시지)은 리스트 형식으로 설정하였습니다.

→ 만약 김유신이 메시지를 두 번 입력했다면 가져오는 리스트의 값의 길이는 2가 되고, 그 index(2)에 해당하는 항목은 마지막으로 입력되는 메시지입니다.

 

- 만약 tag가 변수 my_nickname에 저장된 값과 같다면 imageName을 //me.png로 그렇지 않다면 //you.png로 설정합니다.

→ true 라면 메시지를 자신이 입력했다는 것이고, false라면 다른 사용자가 메시지를 입력했다는 것입니다.

→ 본 채팅앱에는 여러 사용자가 동시에 참여 가능하지만, 이미지는 나와 다른 사용자로만 구분하였습니다.

→ 본 앱의 소스파일을 열어보시면 알겠지만 Designer창의 Media에는 me.png와 you.png가 업로드 되어 있습니다.

 앱인벤터에서는 Media에 올려진 파일을 애셋(asset)이라고 부르며 이 애셋에 대한 경로를 설정할 때 파일명 앞에 슬래시 두 개(//)를 붙입니다.

 

⑪ 리스트뷰 list_Chat의 항목(Elements)을 변수 lv_list에 저장된 값으로 설정합니다.

 

※ 새로운 형식의 리스트뷰의 항목을 블록을 통해 추가할 때는 바로 항목을 리스트뷰에 추가할 수 없고, 위의 예에서 본 것과 같이 다음 과정을 거쳐야 합니다.

1. 리스트 변수 생성

2. 리스트 변수에 call 리스트뷰 이름.CreateElement 블록을 통해 항목 추가

3. Set 리스트뷰 이름.Elements로 리스트뷰의 항목에 리스트 변수를 대입

 

 


 

이상 완벽하지는 않지만 최대한 카카오톡과 비슷한 형식의 채팅앱을 앱인벤터로 만들어 보았습니다.

"숫자로 나타내는 읽음 표시", "나와 상대방의 메시지를 다른 위치에 표시" 등은 여전히 숙제네요...

 

그래도 채팅앱을 만드는 기본원리에 대해서는 알아보았으니 여러분이 더욱 발전시켜 보시기 바랍니다.~~~

댓글