본문 바로가기
프로그래밍/Android

[Android] 비쥬얼 스튜디오로 커스텀 리스트뷰 만들기

by 코딩연습생 2020. 3. 4.
반응형

안녕하세요

 

코딩연습생입니다

 

이번 포스팅은 비쥬얼스튜디오 2017을 이용해서 간단한 안드로이드 앱을 하나 만들어 볼려고 합니다

 

정말 간단합니다ㅎ 

 

아래로 내려지는 스크롤 형식에 리스트뷰를 만들어 볼텐데요

 

일단 글만 보여지는 리스트뷰가 아니라 썸네일형식의 리스트 뷰 형태로 구현을 해볼려고 합니다

 

좌측에 썸네일(이미지)가 있고 그 옆에 제목이 보이는 형식의 리스트뷰 입니다

 

SQL과 연동해서 게시판 형식의 조회 앱을 하나 만들려고 구상 중인데 

 

그 과정중에 하나 입니다

 

1. 비쥬얼 스튜디오 2017을 실행해서 안드로이드 프로젝트를 생성합니다

   - 비쥬얼 스튜디오를 사용해 보신분이라면 굳이 상세하게 설명하지 않아도 쉽게 생성하실꺼라 생각 됩니다

 

자마린 형식의 안드로이트 프로젝트 입니다

 

비어있는 앱 형식의 템플릿을 선택하시고 확인을 눌러 주세요

 

 

2. 프로젝트가 생성이 되면 폴더를 추가해 줍니다 

   - 폴더 명은 Class 입니다

 

폴더가 생성된 모습입니다

 

생성된 폴더에 클래스 파일을 신규로 생성할껀데요

 

방법은 간단합니다 폴더 추가하듯이 마우스 오른쪽으로 클릭하여 생성합니다

 

 

생성할 클래스명은 CustomListView.cs 입니다

 

 

생성된 클래스 파일에 다음과 같이 코딩해 줍니다

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace App.Class
{
    class CustomListView : BaseAdapter
    {
        // Info 클래스에 담긴 데이터를 가지고 있을 Collection
        List<RowInfo> Infos = new List<RowInfo>();

        LayoutInflater Inflater;

        // Collection의 개수(=Row의 개수) 반환
        public override int Count
        {
            get
            {
                return Infos.Count;
            }
        }

        public override Java.Lang.Object GetItem(int position)
        {
            // 자료형이 달라 ListView Row의 정보를 담고있는 RowInfo클래스 자체를 넘길 수 없어 Java의 ArrayList로 반환한다.
            Java.Util.ArrayList infoColumns = new Java.Util.ArrayList();

            infoColumns.Add(Infos[position].Icon);
            infoColumns.Add(Infos[position].Title);
            infoColumns.Add(Infos[position].SubTitle);
            return infoColumns;
        }

        // 지정한 Row의 위치값(Position)을 반환
        public override long GetItemId(int position)
        {
            return position;
        }

        // 생성자에서 inflater의 정보를 얻어온다
        public CustomListView(Context context)
        {
            Inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
        }

        // Position에 위치한 데이터를 화면에 출력하는데 사용될 View를 지정
        // position : 리스트뷰의 RowIndex
        // convertView : 아이템의 화면(만약 아이템의 수가 많아 화면 바깥에 위치할 경우. 아직 생성되지 않은 상태로 있기 때문에 null값이 넘어온다)
        // parent : CustomListView가 얹혀질 ListView의 Container. 부모 View
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ViewHolder holder = null;
            // 화면을 넘어가는 아이템의 경우 스크롤하면 convertView가 null값으로 넘어온다
            if (convertView == null)
            {
                // 미리 만든 ListViewAdater의 정보를 구현해 View로 반환한다.
                convertView = Inflater.Inflate(Resource.Layout.CustomListView, parent, false);

                // holder를 새로 생성하여 Tag에 담아놓는다. convertView가 null이 아닐 경우 새로 생성하지 않고 Tag에 담아놓은 holder를 재사용한다.
                // ViewHolder Class는 아이템 View가 달라질때 마다 새롭게 생성해야 한다/
                // 재활용 View가 null일때 View를 inflate한 후 findViewById를 통해 찾은 View들을 ViewHolder에 저장 후 convertView의 Tag에 저장해놓는다.
                // 그 후 재활용 View를 사용할때는 convertView의 Tag에 있는 ViewHolder를 가져와서 사용하는 구조이다.
                // 이런 구조를 가짐으로써 중복적인 findViewById()를 호출하지 않아 성능적으로 우수한 구조를 가질 수 있다
                holder = new ViewHolder();
                holder.IconView = convertView.FindViewById<ImageView>(Resource.Id.imageView1);
                holder.TitleText = convertView.FindViewById<TextView>(Resource.Id.textView1);
                holder.SubTitleText = convertView.FindViewById<TextView>(Resource.Id.textView2);

                convertView.Tag = holder;
            }
            else
            {
                holder = (ViewHolder)convertView.Tag;
            }

            // holder에 값 대입
            holder.IconView.SetImageDrawable(Infos[position].Icon);
            holder.TitleText.Text = Infos[position].Title;
            holder.SubTitleText.Text = Infos[position].SubTitle;

            return convertView;
        }

        // CustomListView에 아이템을 추가할 함수를 만든다.
        public void AddItem(RowInfo info)
        {
            Infos.Add(info);
            NotifyDataSetChanged();
        }

        public class ViewHolder : Java.Lang.Object
        {
            public ImageView IconView;
            public TextView TitleText;
            public TextView SubTitleText;
        }
    }
}

 

또 하나의 클래스 파일을 생성합니다

 

클래스명은 RowInfo.cs 입니다

 

 

생성된 클래스 파일에 다음과 같이 코딩 합니다

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

using Android.Graphics.Drawables;

namespace App.Class
{
    class RowInfo
    {
        private Drawable pIcon;
        private string pTitle;
        private string pSubTitle;

        public Drawable Icon
        {
            get { return pIcon; }
            set { pIcon = value; }
        }

        public string Title
        {
            get { return pTitle; }
            set { pTitle = value; }
        }

        public string SubTitle
        {
            get { return pSubTitle; }
            set { pSubTitle = value; }
        }
    }
}

 

그 다음 썸네일로 사용할 이미지를 제작해야 하는데

 

제작 어려운 분들을 위해 제가 사용한 샘플 이미지를 올려 드릴께요

 

Drawable.zip
0.00MB

 

위의 그림처럼 Resources -> Drawable 폴더에 해당 png 파일을 넣어줍니다

 

이제는 디자인 화면을 수정 할것입니다

 

Resources -> layout 위치에 axml 파일을 아래 그림과 같이 생성해 줍니다

 

 

CustomListView.axml에 다음과 같으 코딩 합니다

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout1">
        <ImageView
            android:src="@drawable/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView1"
            android:layout_weight="0.1" />
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/linearLayout2"
            android:layout_weight="1">
            <TextView
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/textView1" />
            <TextView
                android:text="Medium Text"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/textView2" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

 

다음 Main.axml 파일에 아래와 같이 코딩 합니다

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <ListView
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listView1" />
</LinearLayout>

 

이번에는 프로젝트가 처음 실행 될때 활성화 부분인 MainActivity.cs 파일을 수정 합니다

 

 

MainActivity.cs 파일을 열어 다음과 같이 코딩 합니다

 

using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using App.Class;

namespace App
{
    [Activity(Label = "CustomListView", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            CustomListView customListView = new CustomListView(this);

            RowInfo info;
            for (int i = 0; i < 100; i++)
            {
                info = new RowInfo();
                info.Icon = GetDrawable(Resource.Drawable.Adobe_Air);
                info.Title = (2 * i).ToString() + "번째 Row Title입니다";
                info.SubTitle = (2 * i).ToString() + "번째 Row SubTitle입니다";
                customListView.AddItem(info);

                info = new RowInfo();
                info.Icon = GetDrawable(Resource.Drawable.Adobe_Flash);
                info.Title = (2 * i + 1).ToString() + "번째 Row Title입니다";
                info.SubTitle = (2 * i + 1).ToString() + "번째 Row SubTitle입니다";
                customListView.AddItem(info);
            }

            ListView listView = FindViewById<ListView>(Resource.Id.listView1);
            listView.Adapter = customListView;
        }
    }
}

 

여기까지 잘 따라하셨다면 프로젝트를 실행할건데요

 

혹시 에뮬레이터 설정을 안하셨다면 아래 링크를 통해 에뮬레이터 설정부터 해주셔야 합니다

 

https://codingman.tistory.com/90

 

[Visual Studio 2017] Microsoft Visual Studio Emulator for Android 설치 하기

안녕하세요 코딩 연습생입니다 이번 포스팅은 비쥬얼스튜디오2017을 이용하여 안드로이드 개발 환경을 구축하기 1단계 입니다 비쥬얼 스튜디오 2017에 에뮬레이터를 설치하여 안드로이드 개발환경을 만들어 보도록..

codingman.tistory.com

 

에뮬레이터까지 설정해주셨다면 빌드를 진행하고 실행 줍니다

 

 

실행이 정상적으로 되셨다면 메뉴 화면에 들어가시면 다음과 같은 아이콘의 앱이 있으실 겁니다

 

 

앱을 실행하시면 아래와 같이 썸네일 형식의 리스트뷰가 보이실 겁니다

 

 

저의 경우 썸네일에 사용하는 이미지 크기를 25x25로 제작하였더니 너무 작게 나오는데요

 

썸네일 이미지를 적당한 크기로 지정하시면 깔끔한 화면에 커스텀 리스트뷰로 사용하실 수 있을거 같습니다

 

반응형

댓글