728x90

 

1. 화면 제어 기초 (한번만 고정할 경우)

 

안드로이드 앱에서

1) 화면을 가로, 세로로 고정시키거나

2) 앱 내에서 API 를 사용해서 센서를 변경하는 방법

 

앱의 화면을 세로(portrait) 또는 가로(landscape) 로 고정하고자 할 경우는 AndroidManifest.xml 에 속성을 지정하면 됩니다. screenOrientation 속성값을 portrait 또는 landscape 로 설정하면 됩니다. (추가적인 속성은 레퍼런스를 참고)

 

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    android:screenOrientation="portrait">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

 

프로그램 내에서 화면을 가로 또는 세로로 고정하거나 센서를 활성화 시키고자 할 경우는

액티비티(Activity) 의 setRequestedOrientation 메소를 사용하면 됩니다.

 

참고로 setContentView가 호출되기 전에 setRequestedOrientation이 호출되어야 함

 

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    //세로 화면으로 고정      
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    //가로 화면으로 고정
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
          
    setContentView(R.layout.main_activity);
}

 

 

 

만약 고정을 풀고 센서를 활성화 하려면 다음과 같이 하면 됩니다.

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

 

 

위의 메소드를 이용하면 특정 상황에서 화면 모드를 설정하고 센서를 활성화 시키는 등의 작업이 가능합니다.

 

 

 

2. 화면 회전을 중간에 변경해야할 경우

2-1. 바람직하지 않은 방법 (1)

  • AndroidManifest.xml에서 모든 Activity에 다음을 추가 한다
android:screenOrientation="portrait" //--- 세로 화면 고정
android:screenOrientation="landscape" //--- 가로 화면 고정

2-1. 바람직하지 않은 방법 (2)

public void onCreate(Bundle savedInstanceState) 함수에서 
setContentView(~); 다음에 아래 라인을 추가 한다. 

// 세로 화면 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
// 가로 화면 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

 

2-2. 화면이 회전해도 Activity가 다시 로딩되지 않도록 하는 방법

안드로이드의 경우 화면이 회전되었을 경우 화면을 종료시키고 새로운 layout으로 재 시작한다. 즉 세로화면 -> 가로화면으로 전환 시 onDestroy() 함수가 호출되고 가로모드에서 다시 onCreate() 함수가 호출된다. 환경변화가 일어날 경우 기본적인 동작은 activity 의 재시작이다.

 이럴때 AndroidManifest.xml 파일에 ` android:configChanges`을 설정함으로써 activity가 reset되는것을 막을 수 있다. 이런경우 activity의 onDestroy()와 onCreate() 함수 대신에 onConfigurationChanged()함수가 호출된다.

 이러한 옵션이 왜 필요한지 예를 들어보자. 사용자의 이름을 입력하는 Edittext를 1개 포함하는 화면이 있다고 하자. 화면이 처음 구성되는 onCreate()함수에서 사용자의 이름변수를 null로 초기화 하고, 화면이 구성된 이후에 사용자가 이름을 입력하였다. 만약 이때 화면이 가로모드에서 세로모드로 변경되면 화면이 종료되고 다시 시작되기 때문에 사용자의 이름변수는 다시 null이 입력되어 있게 된다. 이런 상황에서 원하는 동작은 사용자가 이름을 입력하였기 때문에 Edittext는 사용자가 입력된 내용을 그대로 유지하고 있어야 한다. 이럴때 configChanges 옵션중에서 orientation 옵션을 주면 화면의 방향이 변경되어도 초기화 되지 않는다.

 

Activity가 다시 로딩되지 않으므로 화면의 크기는 변하지 않는다. 따라서 수작업으로 화면을 조정해 주어야 한다.

android:configChanges="orientation | keyboardHidden"

 

위의 옵션은 화면의 방향이 변해도 화면이 초기화 되지 않도록 (android:configChanges="orientation") 한다.

위처럼 | 로 여러개를 셜정할 수 있는데, “keyboardHidden”는 User 가 Hardware Keyboard를 보이고 감추는 등의 Keyboard의 Accessibility가 변경되었을 때의 옵션이다.

 

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    switch(newConfig.orientation) {
        case Configuration.ORIENTATION_PORTRAIT:   
            //--- 수작업으로 세로 화면 생성
            break;
        case Configuration.ORIENTATION_LANDSCAPE:  
            //--- 수작업으로 가로 화면 생성
            break;
    }
}

 

 

화면 회전시 정보를 저장한 후 복구하는 방법

(1) public void onCreate(Bundle savedInstanceState)에 복구와 관련된 코딩을 한다.

(2) public void onDestroy()에 화면 종료와 관련된 코딩을 한다.

 

 

3. 현재 회전 상태 체크 방법

if(getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_90) {
    //가로 모드 일 때
}else{
    //세로 모드 일 때
}

기존에는 .getOrientation()  으로 체크하였으나 최근에는 .getRotation()을 사용하고 있습니다. 리스너로 확인 할 수 있습니다.

getWindowManager().getDefaultDisplay().getOrientation()
getWindowManager().getDefaultDisplay().getRotation()

 

 

Reference

http://www.fun25.co.kr/blog/android-screen-orientation

https://blog.miyam.net/89

https://plogds.tistory.com/265

http://jinyongjeong.github.io/2018/09/30/configchange_option/

https://faith-developer.tistory.com/10

728x90
728x90

 

하단에 고정위치하게 두니, EditText 등을 배치했을 때 버튼이 가려져서 성가셨습니다.

이처럼 불편할 때, 드래그로 움직일 수 있는 FloatingActionButton라면 문제가 없겠죠.

 

package com.example;

import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

public class MovableFloatingActionButton extends FloatingActionButton implements View.OnTouchListener {

    private final static float CLICK_DRAG_TOLERANCE = 10; // Often, there will be a slight, unintentional, drag when the user taps the FAB, so we need to account for this.

    private float downRawX, downRawY;
    private float dX, dY;

    public MovableFloatingActionButton(Context context) {
        super(context);
        init();
    }

    public MovableFloatingActionButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MovableFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent){

        ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)view.getLayoutParams();

        int action = motionEvent.getAction();
        if (action == MotionEvent.ACTION_DOWN) {

            downRawX = motionEvent.getRawX();
            downRawY = motionEvent.getRawY();
            dX = view.getX() - downRawX;
            dY = view.getY() - downRawY;

            return true; // Consumed

        }
        else if (action == MotionEvent.ACTION_MOVE) {

            int viewWidth = view.getWidth();
            int viewHeight = view.getHeight();

            View viewParent = (View)view.getParent();
            int parentWidth = viewParent.getWidth();
            int parentHeight = viewParent.getHeight();

            float newX = motionEvent.getRawX() + dX;
            newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent
            newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent

            float newY = motionEvent.getRawY() + dY;
            newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent
            newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // Don't allow the FAB past the bottom of the parent

            view.animate()
                    .x(newX)
                    .y(newY)
                    .setDuration(0)
                    .start();

            return true; // Consumed

        }
        else if (action == MotionEvent.ACTION_UP) {

            float upRawX = motionEvent.getRawX();
            float upRawY = motionEvent.getRawY();

            float upDX = upRawX - downRawX;
            float upDY = upRawY - downRawY;

            if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click
                return performClick();
            }
            else { // A drag
                return true; // Consumed
            }

        }
        else {
            return super.onTouchEvent(motionEvent);
        }

    }

}

 

XML에서는 다음과 같습니다.

 

    <com.example.MovableFloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_navigate_next_white_24dp"/>

 

Reference

https://stackoverflow.com/questions/46370836/android-movable-draggable-floating-action-button-fab

728x90
728x90

 

//EditText 객체에서 onKeyPreIme 메소드를 재정의

    public boolean onKeyPreIme( int keyCode, KeyEvent event ) {
     
   
     Log.d("AutoCallService", "keyCode : "+keyCode+"");
     Log.d("AutoCallService", "event.getKeyCode() : "+event.getKeyCode()+"");
     switch (event.getAction()) {
     
     case KeyEvent.ACTION_DOWN :
     
     if( event.getAction() == KeyEvent.ACTION_DOWN ) {
     if( keyCode == KeyEvent.KEYCODE_BACK ) {
     this.clearFocus();
     

     Log.d("AutoCallService", "onBackPressed()2");
     }
     }
     break;
     
     
     }
   
return super.onKeyPreIme( keyCode, event );
}

Activity 에서 implements OnEditorActionListener 후


/*@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

if(event.getAction() == KeyEvent.ACTION_DOWN)
{
Log.i("AutoCallService", event.getKeyCode()+"");

}
// TODO Auto-generated method stub
return false;
}*/

 

Reference

http://nerobong2.blogspot.com/2015/12/androidedittext.html

728x90
728x90

1. Bean 주요 속성

  • class(필수): 정규화된 자바 클래스 이름
  • id: bean의 고유 식별자
  • scope: 객체의 범위 (sigleton, prototype)
  • constructor-arg: 생성 시 생성자에 전달할 인수
  • property: 생성 시 bean setter에 전달할 인수
  • init method와 destroy method

2019/10/29 - [Dev/Web] - [Spring] Bean 설정 - beans:bean

 

 

2. Bean Scope

 

 

3. property 정리

http://jwlee1728.egloos.com/v/1805102

 

더보기

일반적인 bean 선언
<bean id="testBean" class="com.ljw.TestBean" />

id : spring container 에서 유일하게 실별할수 있는 이름
class : 해당 bean의 full path

id 대신 name 속성을 사용할수 있음
<bean name="testBean" class="com.ljw.TestBean" />


facotry 클래스의 getInstace 를 통한 bean 설정
<bean id="testFactory" class="com.ljw.TestFactory"
          factory-method="getInstance"/>
factory-method : 해당 클래스의 객체를 반환해주는 메소드(singleton에서)


생성자를 통한 bean 설정
<bean id="testService" class="com.ljw.Service">
    <constructor-arg>
        <ref bean="testDao"/>
    </constructor-arg>
</bean>

<bean id="testDao" class="com.ljw.TestDao"/>
 
ref : reference, 즉 testDao id(혹은 name)를 갖는 bean을 생성자의 인자로 넘겨주겠다는 의미   

<bean id="testService" class="com.ljw.Service">
    <constructor-arg ref="testDao"/>
</bean>
이것 역시 위와 같은 의미

생성자에 특정 값을 넣우줄 때
<bean id="testService" class="com.ljw.Service">
    <constructor-arg>
        <value> 10  </value>
     </constructor-arg>
</bean>

혹은 다음과 같이 작성가능
<bean id="testService" class="com.ljw.Service">
    <constructor-arg value="10"/>
</bean>

<value type="long"> 3000 </value> 같이 value 값의 type을 지정해줄수도 있다(기본적으로 string으로 인식)
즉 생성자가 여러가지 유형이 있을경우 위와같이 type을 설정해주지 않으면 기본적으로 string type의 생성자를 먼저 고려하게됨



property bean 설정 방식(setXXX 함수 를 이용하여 bean 설정)

<bean id="testServcie" class="con.ljw.TestService" >
    <property name="testDao">
        <ref bean="implTestDao"/>
    </property>
</bean>

<bean id="implTestDao" class="con.ljw.ImplTestDao" />

property : TestService class의 setTestDao method를 의미

즉 위의 설정은 TestService class의 setTestDao 메소드를 호출하면서 인자 값으로 ImplTestDao 객체를 넘겨준다는 의미


<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/login/login.mw">loginController</prop>
            </props>
        </property>
    </bean>

props : java.util.properties 클래스로 key, value를 string type으로만 갖는다.
즉 위의 예는 SimpleUrlHandlerMapping 클랙스의  setMappings 메소드를통해 properties 객체를 생성하고
해당 properties 객체는 key="/login/login.mw", value = loginController를 갖고 있게된다.



Bean 객체 범위
<bean name="testDao" class="com.ljw.TestDao"/>

TestDao testDao1 = (TestDao)applicationContext.getBean("testDao");
TestDao testDao2 = (TestDao)applicationContext.getBean("testDao");
위 코드를 통해 생성된 testDao는 동일한 객체이다(스프링 컨테이너 내에서 빈 객체는 싱글턴)

bean scope를 명시하여 서로다른 객체로 생성이 가능한데 다음과 같다.

scope="singleon"  : 기본값이며 스프링 컨테이너당 하나의 빈 객체 생성
scope="prototype" : 빈은 사용할때마다 새로운 객체 생성
scope="request"    :  http 요청마다 새로운 객체 생성(WebApplicationContext에서 사용)
scope="session"    :  세션마다 새로운 객체 생성(WebApplicationContext에서 사용)


<bean name="testDao" class="com.ljw.TestDao" scope="protytype" />
--> bean의 scope 속성값에 설정 하여 사용


list, map 등의 컬렉션 에대한 xml 태크가 있긴하지만 위에 정리된 부분만 봐도
spring xml에 대해 이해가 될거라 판단됨.

 

 

 

Reference

https://gmlwjd9405.github.io/2018/11/10/spring-beans.html

https://offbyone.tistory.com/325

http://jwlee1728.egloos.com/v/1805102

 

728x90

+ Recent posts