ScrollView 에 자동으로 가져온 데이터를 화면 출력하고 스크롤이 되도록 하는 샘플 코드다.
TextView 옵션을 못찾아 구글링으로 관련 코드를 찾으라 한참 삽질하고 동작 확인하고 세부 구현을 위한 기초 데이터로서는 되겠다 싶어 기초사항을 적는다.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
<Button android:id="@+id/btn_service_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="서비스 시작" />
<Button android:id="@+id/btn_service_end" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="서비스 종료" />
<Button android:id="@+id/btn_service_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textAllCaps="false" android:text="데이터 Get" />
<Button android:id="@+id/btn_clear_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textAllCaps="false" android:text="화면 Clear" />
</LinearLayout>
<ScrollView android:id="@+id/scrollview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="5dp" android:layout_weight="1" android:descendantFocusability="beforeDescendants" android:gravity="center" android:background="#000000">
<TextView android:id="@+id/consoleText" android:layout_width="match_parent" android:layout_height="40dp" android:layout_margin="5dp" android:textIsSelectable="false" android:gravity="left" android:textColor="#FFFFFF"/> </ScrollView>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="3">
<EditText android:id="@+id/EtInput" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="3" android:inputType="textMultiLine" android:lines="2" android:hint="명령어를 입력하세요" />
<Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:text="send" /> </LinearLayout> </LinearLayout>
|
import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log;
import static android.content.ContentValues.TAG;
public class getDataCallService extends Service { IBinder mBinder = new DataCallBinder();
public getDataCallService() { }
class DataCallBinder extends Binder { getDataCallService getService() { // 서비스 객체를 리턴 return getDataCallService.this; } }
public String getBroastData(){ return "getDataCallService data\n Line Feed."; }
@Override public IBinder onBind(Intent intent) { Log.d(TAG, "서비스 onBind 에서 시작"); return mBinder; }
@Override public void onCreate() { super.onCreate(); }
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "서비스 시작"); return super.onStartCommand(intent, flags, startId); }
@Override public void onDestroy() { Log.d(TAG, "서비스 종료"); super.onDestroy(); } }
|
import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.text.InputType; import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast;
public class MainActivity extends AppCompatActivity { Context context; getDataCallService ms; // 서비스 boolean isService = false; // 서비스 실행 확인 TextView mDumpTextView; ScrollView mScrollView; private Runnable mScrollingRunnable;
public EditText editText; public Button send;
ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 서비스와 연결되었을 때 호출되는 메서드 getDataCallService.DataCallBinder mb = (getDataCallService.DataCallBinder) service; ms = mb.getService(); isService = true; }
@Override public void onServiceDisconnected(ComponentName name) { isService = false; } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this.getBaseContext();
Button btnStart = (Button) findViewById(R.id.btn_service_start); Button btnEnd = (Button) findViewById(R.id.btn_service_end); Button btnCallData = (Button) findViewById(R.id.btn_service_data); Button btnClearData = (Button) findViewById(R.id.btn_clear_data); mScrollView = findViewById(R.id.scrollview); mDumpTextView = (TextView) findViewById(R.id.consoleText); editText = (EditText) findViewById(R.id.EtInput); send = (Button) findViewById(R.id.send);
final SoftKeyboardDectectorView softKeyboardDecector = new SoftKeyboardDectectorView(this); addContentView(softKeyboardDecector, new FrameLayout.LayoutParams(-1, -1));
softKeyboardDecector.setOnShownKeyboard(new SoftKeyboardDectectorView.OnShownKeyboardListener() { @Override public void onShowSoftKeyboard() { //키보드 등장할 때 채팅창 마지막 입력 내용을 바로 보이도록 처리 mScrollView.fullScroll(ScrollView.FOCUS_DOWN); } });
btnStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 서비스 시작하기 Intent intent = new Intent(getApplicationContext(), getDataCallService.class); bindService(intent,connection, Context.BIND_AUTO_CREATE); } });
btnEnd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 서비스 종료 unbindService(connection); } });
btnClearData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mDumpTextView.setText(""); mScrollView.invalidate(); } });
// message send action send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!editText.getText().toString().isEmpty()) { updateReceivedData(editText.getText().toString()); editText.setText(" "); } } });
mScrollView.setVerticalScrollBarEnabled(true); // 수직방향 스크롤바 사용 가능하도록 설정 mScrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; // 이건 기능 테스트 목적으로 아직 구현이 안된 상태 } });
btnCallData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!isService){ Toast.makeText(getApplicationContext(), "서비스가 실행중이 아닙니다.", Toast.LENGTH_SHORT).show(); } else { String data = ms.getBroastData(); // 서비스에서 가져온 데이터 updateReceivedData(data); } } }); }
private void updateReceivedData(String data) { // 콘솔 결과 데이터라 가정하고 테스트 함 final String message = data + "\n"; // 실제 USB 콘솔 연결시에는 \n 은 삭제처리하는게 좋음 mDumpTextView.append(message); mDumpTextView.setTextColor(Color.WHITE); mDumpTextView.setTextIsSelectable(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mDumpTextView.setElegantTextHeight(true); } mDumpTextView.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION); mDumpTextView.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE); mDumpTextView.setSingleLine(false); refreshView(); }
private void refreshView(){ mScrollView.postDelayed(new Runnable() { @Override public void run() { mScrollView.fullScroll(ScrollView.FOCUS_DOWN); } },100); //mScrollView.setScrollY(View.FOCUS_DOWN); mScrollView.smoothScrollTo(0, mDumpTextView.getBottom()); } }
|
import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View;
public class SoftKeyboardDectectorView extends View { // 출처 : http://givenjazz.tistory.com/54 private boolean mShownKeyboard; private OnShownKeyboardListener mOnShownSoftKeyboard; private OnHiddenKeyboardListener onHiddenSoftKeyboard;
public SoftKeyboardDectectorView(Context context) { this(context, null); }
public SoftKeyboardDectectorView(Context context, AttributeSet attrs) { super(context, attrs); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { Activity activity = (Activity)getContext(); Rect rect = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight(); int diffHeight = (screenHeight - statusBarHeight) - h; if (diffHeight > 100 && !mShownKeyboard) { // 모든 키보드는 100px보다 크다고 가정 mShownKeyboard = true; onShownSoftKeyboard(); } else if (diffHeight < 100 && mShownKeyboard) { mShownKeyboard = false; onHiddenSoftKeyboard(); } super.onSizeChanged(w, h, oldw, oldh); }
public void onHiddenSoftKeyboard() { if (onHiddenSoftKeyboard != null) onHiddenSoftKeyboard.onHiddenSoftKeyboard(); }
public void onShownSoftKeyboard() { if (mOnShownSoftKeyboard != null) mOnShownSoftKeyboard.onShowSoftKeyboard(); }
public void setOnShownKeyboard(OnShownKeyboardListener listener) { mOnShownSoftKeyboard = listener; }
public void setOnHiddenKeyboard(OnHiddenKeyboardListener listener) { onHiddenSoftKeyboard = listener; }
public interface OnShownKeyboardListener { public void onShowSoftKeyboard(); }
public interface OnHiddenKeyboardListener { public void onHiddenSoftKeyboard(); }
}
|
ScrollView 에서 TextView 값이 넘어오면 자동으로 화면이 스크롤 되도록 처리하는 것이 필요하다고 판단되어 관련 코드를 구글링하여 테스트하고 적었다.
아직 세부적으로 기능 설명은 적지 못했다.