'2019/02/19'에 해당되는 글 1건

728x90

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 값이 넘어오면 자동으로 화면이 스크롤 되도록 처리하는 것이 필요하다고 판단되어 관련 코드를 구글링하여 테스트하고 적었다.

아직 세부적으로 기능 설명은 적지 못했다.

블로그 이미지

Link2Me

,