물에 살고싶은 개발자

AutocompleteTextview 예제 및 구분선 스타일링 방법 본문

Android

AutocompleteTextview 예제 및 구분선 스타일링 방법

돼지사랑 2019. 5. 16. 14:48

자동완성을 구현하기 위한 방법 중 하나인 오토컴플릿텍스트뷰에 대한 간략한 설명 + 구현된 이미지

자동완성을 구현하기 위한 방법은 다양하지만, 이번에는 AutocompleteTextview(이하 AT)를 이용한 방법을 소개하려 한다.

(사실 나중에 내가보려고 쓰는거다)

AT는 자동완성을 구현하는 여러 방법중 서버에서 키워드를 한번에 전부 받아와서 클라이언트에서 키워드를 검색해서 보여줄때 쓰기 좋은 기능이다.


결과 이미지(커스터마이징 된 결과물)

이런식으로 사용할 수도 있다. 나머지는 각설하고 사용법 ㄱㄱ

 

1. 가장 기본적인 사용법에 대한 예제

기본적인 사용법이다. 어댑터를 따로 생성하지 않고 세팅할때 즉석으로 만들어 사용하며, 뷰도 따로 만들지 않는다.

(아래 소개할 예제 코드는 이 블로그에서 퍼온것을 밝힌다.)


사용하려는 액티비티

MainActivity.java 

public class MainActivity extends Activity {
private List<String> list; // 데이터를 넣은 리스트변수

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 검색어 데이터가 들어갈 리스트
list = new ArrayList<>();

// 리스트에 데이터 추가
settingList();

//자동완성 뷰 정의
final AutoCompleteTextView autoCompleteTextView = findViewById(R.id.autoCompleteTextView);

// AutoCompleteTextView 의 단어 출력을 위해 어댑터 연결
autoCompleteTextView.setAdapter(new ArrayAdapter<>(this,
android.R.layout.simple_dropdown_item_1line, //안드로이드에서 제공하는 기본적으로 있는 드롭다운 아이템
list)); //위에서 생성한 리스트
}

// 자동완성을 위한 검색어 데이터 추가
private void settingList(){
list.add("채수빈");
list.add("박지현");
list.add("수지");
list.add("남태현");
list.add("하성운");
list.add("크리스탈");
list.add("강승윤");
list.add("손나은");
list.add("남주혁");
list.add("루이");
list.add("진영");
list.add("슬기");
list.add("이해인");
list.add("고원희");
list.add("설리");
list.add("공명");
list.add("김예림");
list.add("혜리");
list.add("웬디");
list.add("박혜수");
list.add("카이");
list.add("진세연");
list.add("동호");
list.add("박세완");
list.add("도희");
list.add("창모");
list.add("허영지");
}
}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context=".MainActivity">

<AutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center_vertical"
android:textColorHint="#555555"
android:completionHint="검색어를 입력하세요."
android:completionThreshold="1" />

</android.support.constraint.ConstraintLayout>


끝이다. 매우 심플하다. 아래는 결과


입력 전


입력 후


이걸로 끝이다. 별다른 디자인이 없다면 이렇게 써도 무방할것이다.

하지만 우리는 대부분의 경우 이것만으로는 만족하지 못한다.

그래서 준비했다.


2. 기본적인 Custom AT 예제


(아래 소개할 예제코드는 이 블로그에서 퍼왔음을 밝힌다.)


이번엔 아래 이미지와 같은 모양으로 만들어볼거다.



일단 액티비티와 아이템 객체

public class MainActivity extends Activity {

//검색어 데이터를 넣을 리스트
private List<CountryItem> countryList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fillCountryList();

AutoCompleteTextView AT = findViewById(R.id.autoCompleteTextView);

//커스텀 어댑터를 생성
AutoCompleteAdapter adapter = new AutoCompleteAdapter(this, countryList);
//생성한 어댑터를 AT에 세팅
AT.setAdapter(adapter);
}

//검색어 데이터 추가
private void fillCountryList() {
countryList = new ArrayList<>();
countryList.add(new CountryItem("Afghanistan", R.drawable.screenshot_1));
countryList.add(new CountryItem("albanaia", R.drawable.screenshot_2));
countryList.add(new CountryItem("Algeria", R.drawable.screenshot_3));
countryList.add(new CountryItem("Korea", R.drawable.screenshot_4));
}
}
public class CountryItem {
private String countryName;
private int flagImage;

public CountryItem(String countryName, int flagImage) {
this.countryName = countryName;
this.flagImage = flagImage;
}

public String getCountryName() {
return countryName;
}

public int getFlagImage() {
return flagImage;
}

}

특별하게 달라진건 없다. 아이템에 이미지를 추가하기 위해 아이템객체를 추가한것뿐.


다음은 액티비티의 xml 

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context=".MainActivity">

<AutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="300dp"
android:layout_height="45dp"
android:layout_marginTop="16dp"
android:background="@drawable/radius17_back_ebebeb"
android:completionThreshold="1"
android:gravity="center_vertical"
android:hint="검색어를 입력하세요."
android:paddingLeft="10dp"
android:textColorHint="#555555"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

radius17_back_ebebeb.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<corners android:radius="17dp" />
<solid android:color="#EBEBEB" />
</shape>
</item>
</layer-list>


여기까지 하면 AT의 모양이 바뀐다. 다음은 어댑터를 보자


AT어댑터

//ArrayAdapter 상속을 받는다. 꼭 ArrayAdapter 가 아니어도 됨.
class AutoCompleteAdapter extends ArrayAdapter<CountryItem> {

//데이터를 넣을 리스트
private List<CountryItem> countryListFull;

public AutoCompleteAdapter(@NonNull Context context, @NonNull List<CountryItem> countryList) {
super(context, 0, countryList);
countryListFull = new ArrayList<>(countryList);
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.country_autocomplete_row, parent, false
);
}

TextView textView = convertView.findViewById(R.id.text_view_name);
ImageView imageView = convertView.findViewById(R.id.image_view_flag);

//getItem(position) 코드로 자동완성 될 아이템을 가져온다
CountryItem countryItem = getItem(position);

if (countryItem != null) {
textView.setText(countryItem.getCountryName());
imageView.setImageResource(countryItem.getFlagImage());
}
return convertView;
}

//-------------------------- 이 아래는 자동완성을 위한 검색어를 찾아주는 코드이다 --------------------------
@NonNull
@Override
public Filter getFilter() {
return countryFilter;
}

private Filter countryFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {

FilterResults results = new FilterResults();
List<CountryItem> suggestions = new ArrayList<>();

if (constraint == null || constraint.length() == 0) {
suggestions.addAll(countryListFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();

for (CountryItem item : countryListFull) {
if (item.getCountryName().toLowerCase().contains(filterPattern)) {
suggestions.add(item);
}
}
}

results.values = suggestions;
results.count = suggestions.size();

return results;
}

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
addAll((List) results.values);
notifyDataSetChanged();
}

@Override
public CharSequence convertResultToString(Object resultValue) {
return ((CountryItem) resultValue).getCountryName();
}
};


}


어댑터에서 쓸 아이템 

country_autocomplete_row.xml

<?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="wrap_content"
android:orientation="horizontal"
android:padding="4dp"
xmlns:tools="http://schemas.android.com/tools">

<ImageView
android:id="@+id/image_view_flag"
tools:src="@drawable/screenshot_4"
android:layout_width="60dp"
android:layout_height="40dp" />

<TextView
android:id="@+id/text_view_name"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
tools:text="korea"/>

</LinearLayout>

코드에 주석으로 대략적인 설명을 붙여놨다. 


이렇게까지 하면 마음대로 커스텀할 수 있는 커스텀 AT가 완성된다.


3. 추가 스타일링


추가로 구분선이나 드롭다운 메뉴창의 위치같은걸 변경하는 방법은 아래와 같다.

우선  드롭다운 메뉴를 조정하는 방법

AT를 세팅하는 class.java 에서

AT.setDropDownBackgroundResource(R.color.transparent); //드롭다운메뉴의 배경을 세팅하는 코드. 해당 컬러는 #00000000 으로 투명이다
AT.setDropDownVerticalOffset(500); //드롭다운 창의 위치를 조정 가로세로 두가지가 있다.


그리고 구분선 커스텀하는 방법

style.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:dropDownListViewStyle">@style/MyListViewStyle</item>
</style>


<style name="MyListViewStyle" parent="@android:style/Widget.ListView">
<item name="android:divider">#F00</item>
<item name="android:dividerHeight">10dp</item>
</style>

아래처럼 MyListViewSytyle에서 divider 값들을 원하는대로 세팅하면된다.



이 두가지를 적용한 결과를 보자


무엇이 변했는지 보기좋으라고 단위를 쌔게 때렸다.

보면 알겠지만, 드롭다운이 꽤나 아래로 내려왔고, 구분선이 빨간색 두껍게 있는걸 알 수 있다.


저 구분선을 스타일링때문에 이리저리 검색하다 두시간인가 날려먹어서 글을 작성하게 됏다ㅡㅡ

style은 앱 전체에 영향을 끼치지때문에 왠만하면 쓰고싶지 않았는데,

생각해보니 지금 프로젝트에서는 ListView를 쓰지 않기때문에 쿨하게 사용했다.(앞으로도 ListView는 안쓸거같긴 하지만 ㅋ;;)

아무튼 검색하느라 고통받은 내용들이라 블로그 글을 작성한다.


끗!!



Ps.구분선(divider)땜에 2시간 날려먹었는데 글작성하는데도 2시간걸림..

Comments