반응형

AndroidManifest.xml

<!-- adjustResize 속성 추가 -->
<activity android:name=".MainActivity"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="adjustResize"/>

선언

SoftKeyboard softKeyboard;

이벤트 등록

//키보드 show/hide 이벤트
void setKeyboardEvent() {
    InputMethodManager controlManager = (InputMethodManager)getSystemService(Service.INPUT_METHOD_SERVICE);
    softKeyboard = new SoftKeyboard((LinearLayout)findViewById(R.id.linear_root), controlManager);
    softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged() {
        @Override
        public void onSoftKeyboardHide() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    //Toast.makeText(getApplication(),"키보드 내려감",Toast.LENGTH_SHORT).show();
                }
            });
        }
 
        @Override
        public void onSoftKeyboardShow() {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    //Toast.makeText(getApplication(),"키보드 올라감",Toast.LENGTH_SHORT).show();
                }
            });
        }
    });
}

SoftKeyboard.java

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
 
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
 
public class SoftKeyboard implements View.OnFocusChangeListener
{
	private static final int CLEAR_FOCUS = 0;
 
	private ViewGroup layout;
	private int layoutBottom;
	private InputMethodManager im;
	private int[] coords;
	private boolean isKeyboardShow;
	private SoftKeyboardChangesThread softKeyboardThread;
	private List<EditText> editTextList;
 
	private View tempView; // reference to a focused EditText
 
	public SoftKeyboard(ViewGroup layout, InputMethodManager im)
	{
		this.layout = layout;
		keyboardHideByDefault();
		initEditTexts(layout);
		this.im = im;
		this.coords = new int[2];
		this.isKeyboardShow = false;
		this.softKeyboardThread = new SoftKeyboardChangesThread();
		this.softKeyboardThread.start();
	}
 
 
	public void openSoftKeyboard()
	{
		if(!isKeyboardShow)
		{
			layoutBottom = getLayoutCoordinates();
			im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
			softKeyboardThread.keyboardOpened();
			isKeyboardShow = true;
		}
	}
 
	public void closeSoftKeyboard()
	{
		if(isKeyboardShow)
		{
			im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
			isKeyboardShow = false;
		}
	}
 
	public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback)
	{
		softKeyboardThread.setCallback(mCallback);
	}
 
	public void unRegisterSoftKeyboardCallback()
	{
		softKeyboardThread.stopThread();
	}
 
	public interface SoftKeyboardChanged 
	{
		public void onSoftKeyboardHide();
		public void onSoftKeyboardShow();	
	}
 
	private int getLayoutCoordinates()
	{
		layout.getLocationOnScreen(coords);
		return coords[1] + layout.getHeight();
	}
 
	private void keyboardHideByDefault()
	{
		layout.setFocusable(true);
		layout.setFocusableInTouchMode(true);
	}
 
	/*
	 * InitEditTexts now handles EditTexts in nested views
	 * Thanks to Francesco Verheye (verheye.francesco@gmail.com)
	 */
	private void initEditTexts(ViewGroup viewgroup) 
	{
		if(editTextList == null)
			editTextList = new ArrayList<EditText>();
 
		int childCount = viewgroup.getChildCount();
		for(int i=0; i<= childCount-1;i++) 
		{
			View v = viewgroup.getChildAt(i);
 
			if(v instanceof ViewGroup) 
			{
				initEditTexts((ViewGroup) v);
			}
 
			if(v instanceof EditText) 
			{
				EditText editText = (EditText) v;
				editText.setOnFocusChangeListener(this);
				editText.setCursorVisible(true);
				editTextList.add(editText);
			}
		}
	}
 
	/*
	 * OnFocusChange does update tempView correctly now when keyboard is still shown
	 * Thanks to Israel Dominguez (dominguez.israel@gmail.com)
	 */
	@Override
	public void onFocusChange(View v, boolean hasFocus) 
	{
		if(hasFocus) 
		{
			tempView = v;
			if(!isKeyboardShow) 
			{
				layoutBottom = getLayoutCoordinates();
				softKeyboardThread.keyboardOpened();
				isKeyboardShow = true;
			}
		}
	}
 
	// This handler will clear focus of selected EditText
	private final Handler mHandler = new Handler()
	{
		@Override
		public void handleMessage(Message m)
		{
			switch(m.what)
			{
			case CLEAR_FOCUS:
				if(tempView != null)
				{
					tempView.clearFocus();
					tempView = null;
				}
				break;
			}
		}
	};
 
	private class SoftKeyboardChangesThread extends Thread
	{
		private AtomicBoolean started;
		private SoftKeyboardChanged mCallback;
 
		public SoftKeyboardChangesThread()
		{
			started = new AtomicBoolean(true);
		}
 
		public void setCallback(SoftKeyboardChanged mCallback)
		{
			this.mCallback = mCallback;
		}
 
		@Override
		public void run()
		{
			while(started.get())
			{
				// Wait until keyboard is requested to open
				synchronized(this)
				{
					try 
					{
						wait();
					} catch (InterruptedException e) 
					{
						e.printStackTrace();
					}
				}
 
				int currentBottomLocation = getLayoutCoordinates();
 
				// There is some lag between open soft-keyboard function and when it really appears.
				while(currentBottomLocation == layoutBottom && started.get())
				{
					currentBottomLocation = getLayoutCoordinates();
				}
 
				if(started.get())
					mCallback.onSoftKeyboardShow();
 
				// When keyboard is opened from EditText, initial bottom location is greater than layoutBottom
				// and at some moment equals layoutBottom.
				// That broke the previous logic, so I added this new loop to handle this.
				while(currentBottomLocation >= layoutBottom && started.get())
				{
					currentBottomLocation = getLayoutCoordinates();
				}
 
				// Now Keyboard is shown, keep checking layout dimensions until keyboard is gone
				while(currentBottomLocation != layoutBottom && started.get())
				{
                                        synchronized(this)
					{
						try 
						{
							wait(500);
						} catch (InterruptedException e) 
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					currentBottomLocation = getLayoutCoordinates();
				}
 
				if(started.get())
					mCallback.onSoftKeyboardHide();
 
				// if keyboard has been opened clicking and EditText.
				if(isKeyboardShow && started.get())
					isKeyboardShow = false;
 
				// if an EditText is focused, remove its focus (on UI thread)
				if(started.get())
					mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget();
			}	
		}
 
		public void keyboardOpened() {
			synchronized(this) {
				notify();
			}
		}
 
		public void stopThread() {
			synchronized(this) {
				started.set(false);
				notify();
			}
		}
	}
}
반응형

'안드로이드' 카테고리의 다른 글

Android ViewPager  (0) 2021.11.14
Android Webview(Remote, Local)  (2) 2021.11.14
Android Permission(권한 요청)  (0) 2021.11.14
Android adb 사용  (0) 2021.11.14
Android Version List  (1) 2021.11.14
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기