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의 역활은 특별히 없지요?
답글삭제원하면 텍스트뷰를 빼도 되는가요?
네 없어도 될거 같습니다
삭제