Focus 문제
EditText 를 선택하면 focus 가 제대로 가지 않는 문제가 있었다.
AndroidManifest.xml 수정: 해당 activity 에 아래 속성을 추가
android:windowSoftInputMode="adjustPan"
EditText 에 입력하는 내용을 ListView 에 적용
- 시도 1) EditText 에 onFocusChangedListener 를 입력하고 focus 를 잃을 때 ListView adapter 를 업데이트 하게 했다.
- 키보드 눌릴 때 마다 focus 를 잠깐 잃었다가 다시 들어와서 실패
- 시도 2) EditText 에 onEditorActionListener 를 입력하고 사용자 입력이 끝나면 ListView adpater 를 업데이트하게 했다.
- 이벤트가 제대로 오지 않았다.
- 결론
- EditText 변경이 끝나는 시점을 찾아서 ListView adpater 를 업데이트 하는 거는 실패했다.
- 단지 해당 아이템에 값만 변경해 주면 되었다. (아래와 같은 이유)
- EditText 가 보이는 동안에는 입력한 내용이 보일 것이다.
- EditText 가 보이지 않았다가 보이게 되는 경우 adapter 의 getView() 함수가 불리면서 알아서 갱신된다.
- *) EditText 에 addTextChangedListener() 함수를 이용해서 text 변경시 마다 listview item 에 반영했다.
예
activity_main.xml:
EditText 외의 영역을 건드리면 EditText 의 focus 없애기
EditText 이외의 모든 view 에 OnTouchListener 를 등록하고 touch 하면 키보드를 숨기고 해당 view 로 focus 를 이동하게 한다.
{키보드 숨기기}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
layout_list_item.xml:<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sample"
android:layout_weight="0.3" />
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.7"/>
</LinearLayout>
MainActivity.java:import android.content.Context;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends ActionBarActivity {
private ListView listView;
private List<Item> list = new ArrayList<Item>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int i = 0; i < 30; i++) {
list.add(new Item("Item" + (i+1), "" + i));
}
listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(new MyAdapter(this, list));
}
private class Item {
public String text;
public String edit;
public Item(String text, String edit) {
this.text = text;
this.edit = edit;
}
}
private class MyWatcher implements TextWatcher {
private EditText edit;
private Item item;
public MyWatcher(EditText edit) {
this.edit = edit;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.d("TAG", "onTextChanged: " + s);
this.item = (Item)edit.getTag();
if (item != null) {
item.edit = s.toString();
}
}
@Override
public void afterTextChanged(Editable s) {
}
}
private class MyAdapter extends ArrayAdapter<Item> {
private final static int resId = R.layout.layout_list_item;
private Context context;
List<Item> list;
public MyAdapter(Context context, List<Item> list) {
super(context, resId, list);
this.context = context;
this.list = list;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
Item item = getItem(position);
if (v == null) {
v = getLayoutInflater().inflate(resId, null);
EditText et = (EditText)v.findViewById(R.id.edit);
et.addTextChangedListener(new MyWatcher(et));
}
TextView tv = (TextView)v.findViewById(R.id.text);
EditText et = (EditText)v.findViewById(R.id.edit);
et.setTag(item);
tv.setText(item.text);
et.setText(item.edit);
return v;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
EditText 외의 영역을 건드리면 EditText 의 focus 없애기
EditText 이외의 모든 view 에 OnTouchListener 를 등록하고 touch 하면 키보드를 숨기고 해당 view 로 focus 를 이동하게 한다.
{키보드 숨기기}
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
{Root view 얻기}
아무 view 나 getRootView() 함수를 이용해서 얻는다.
view.getRootView()
예)
public void hideSoftKeyboard() {
InputMethodManager imm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
public void inspireViewsHideKeyboardOnTouch(View v, boolean recursive) {
if (!(v instanceof EditText)) {
v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard();
v.requestFocus();
return false;
}
});
}
if (recursive && v instanceof ViewGroup) {
ViewGroup g = (ViewGroup)v;
for (int i = 0; i < g.getChildCount(); i++) {
inspireViewsHideKeyboardOnTouch(g.getChildAt(i), recursive);
}
}
}
안녕하세요 졸업프로젝트를 하다 리스트뷰의 에딧텍스트부분에 값을 받는곳에서 막혔는데요. 해결하신 방법대로 시도해보고있는데 item에 어떤식으로 반영하는지 설명해주실 수 있나요ㅜ?
답글삭제본문에 예제를 추가 드렸지만 워낙 예외 상황이 많은지라 위 예제 방법 보다는 EditText 에 클릭 이벤트를 처리하여 다이얼로그를 하나 띄워서 입력 받는 방법이 더 확실한 거 같습니다.
삭제참고 바랍니다.
감사합니다!! 며칠간 이 문제로 헤메고있었는데 잘 해결했습니다 !!
삭제혹시 이 예제에서 TextView의 역활은 특별히 없지요?
답글삭제원하면 텍스트뷰를 빼도 되는가요?
네 없어도 될거 같습니다
삭제