[Android] 키보드가 나타날 때 ListView 자동 스크롤

16140 단어 AndroidJava
키보드가 편집 텍스트의 초점 등에 나타날 때, ListView는 자동으로 임의의 위치 (항목) 로 스크롤할 수 있습니다.
이해하기 어렵지만 완성형은 이런 느낌이에요.
     

키보드 표시 감지


View#onSizeChanged를 연결하여 뷰의 크기를 키보드에 표시되는 방법으로 변경합니다.
Activity와 Fragment가 사이즈 변경을 처리할 수 있도록 우선 ListView를 확장하는 반을 만들어야 한다.
다음은 onSizeChanged에서 전화를 한 후 청중을 onKeyboad Apperard라고 부른다.
CustomListView.java

package com.example.scrollsample;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class CustomListView  extends ListView{

    //ActivityまたはFragmentが実装するインターフェース
    public interface OnKeyboardAppearedListener {
        public void onKeyboardAppeared(boolean isChange);
    }
    private OnKeyboardAppearedListener listener;


    public CustomListView(Context context) {
        super(context);
    }

    //このコンストラクタが無いとXMLからインフレートできないので注意
    public  CustomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public  CustomListView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

    //リスナー登録のメソッド
    public void setListener(OnKeyboardAppearedListener listener) {
        this.listener = listener;
    }

    //Viewのサイズが変化した時に呼ばれるメソッド
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w,h,oldw,oldh);

        //キーボード出現時(Viewのサイズが小さくなった場合)のみ
        if(h < oldh){
            //インターフェースを実装したリスナー(Activity、Fragment)のメソッドを呼ぶ
            listener.onKeyboardAppeared(true);          
        }       
    }
}

임의의 위치로 스크롤


Activity와 Fragment를 통해 OnKeyboard Appered Listener를 implements로 사용하고, onKeyboard Appered 방법을 다시 쓰면 키보드 출현(View의 사이즈 변경)을 처리할 수 있다.
스크롤은 ListView#smoothScrollToPosition을 사용합니다.
View의 사이즈 변경이 완료되지 않으면 작업이 잘 되지 않기 때문에handler#postDelayed를 사용하여 시간을 지연시킵니다.(더 좋은 방법이 있다면 반드시.)
또한 애니메이션을 스크롤하지 않고도 ListView#setSelection을 사용할 수 있습니다.
smothScrollToPosition의 매개 변수가position(항목 번호)을 지정하기 때문에 프로젝트 총수에서 1의 번호를 빼면 마지막 항목으로 스크롤됩니다.
main.fragment

public class MainFragment extends Fragment implements OnKeyboardAppearedListener{

    private CustomListView listView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_main, container, false);

        //CustomListView
        listView = (CustomListView) view.findViewById(R.id.listView);
        //リスナー登録
        listView.setListener(this);

        //ダミーのitemをCustomListViewにセット
        String[] memnuStrings = { "item0","item1","item2","item3","item4","item5","item6","item7","item8","item9","item10","item11","item12", "item13","item14","item15","item16","item17","item18","item19","item20"};
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, memnuStrings);
        listView.setAdapter(adapter);

        return view;
    }

    @Override
    public void onKeyboardAppeared(boolean isChange) {

        //ListView生成済、且つサイズ変更した(キーボードが出現した)場合
        if(isChange){

            //リストアイテムの総数-1(0番目から始まって最後のアイテム)にスクロールさせる           
            Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    //リストアイテムの総数-1(0番目から始まって最後のアイテム)にフォーカスさせる
                    listView.smoothScrollToPosition(listView.getCount()-1);
                }
            };
            handler.postDelayed(runnable, 500);

            //スクロールアニメーションが要らない場合はこれでOK
            //listView.setSelection(listView.getCount()-1);
        }
    }   
}

레이아웃 정의


참고로 Custom ListView는 레이아웃의 xml 파일로 편입되어 있습니다.
fragment_main
<?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="match_parent"
    android:orientation="vertical" >

    <!-- カスタムリストビュー -->
    <com.example.scrollsample.CustomListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollingCache="false" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#CCC"
        android:orientation="horizontal"
        android:padding="6dp" >

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#FFF"
            android:focusableInTouchMode="true"
            android:inputType="textMultiLine"
            android:maxLength="200"
            android:padding="6dp"
            android:textSize="18sp" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="6dp"
            android:text="Button"
            android:textSize="12sp" />
    </LinearLayout>

</LinearLayout>

끝말


솔직히 미묘하게 사용하긴 했지만 ListView로 채팅 UI와 입력 형식이 있는 설정 화면을 만들려고 하는 상황에서 혹시 사용할 수 있을까요?

좋은 웹페이지 즐겨찾기