728x90

이번에는 뷰 플리퍼(ViewFlipper)에 대해서 살펴 보겠습니다.


안드로이드에 뷰 플리퍼는 여러개의 뷰를 한 화면씩 보여주는 것입니다.

탭과 비슷하지만 탭버튼 등 이 없는 것이지요.


안드로이드 OS 의 타겟이 대부분 모바일용 기기라고 봤을 때,

뷰 플리퍼는 탭보다 오히려 유용할때가 많습니다.


탭은 특정한 탭버튼을 사용하여 다른 탭으로 전환 가능하지만,

뷰 플리퍼는 시간에 따라 화면이 바뀌게 하거나 모션 센서 등을 이용하는 등

모바일 기기 특성을 이용할 때 유용합니다. 사실 탭위젯으로도 똑같은 작업을 할 수 있겠지만, 훨씬 번거롭겠죠.


즉 탭위젯으로 특정 뷰를 분리할 필요가 없는 경우는 뷰 플리퍼를 자주 사용한다고 생각됩니다.


먼저 특정 버튼을 눌렀을때 화면이 바뀌는 뷰 플리퍼 예제를 구현해 보겠습니다.


레이아웃 xml 소스를 다음과 같이 편집합니다.


layout/main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<Button  

android:id="@+id/button_next"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="next view"

    />

<ViewFlipper

android:id="@+id/viewFlipper_details"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="first page">

</TextView>

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="second page">

</TextView>

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="third page">

</TextView>

</ViewFlipper>

</LinearLayout>


LinearLayout  에 버튼 하나와 뷰 플리퍼를 넣은 모습입니다.

뷰 플리퍼는 세개의 ChildView 를 지니고, 각 ChildView는 간단한 텍스트 뷰 입니다.


뷰 플리퍼 역시 프레임 레이아웃 클래스를 상속받기 때문에,

내부에 또 다른 뷰를 지닐수 있고, addView() 메소드를 이용하여 새로운 뷰를 추가할 수 도 있습니다.


보다 자세한건 레퍼런스를 참조하도록 하겠습니다.


 



바로 위의 부모 클래스인 ViewAnimator 클래스는 보다 

일반적인 뷰의 전환을 보여주는 클래스라고 생각할 수 있습니다.

뷰 플리퍼는 뷰 애니메이터를 상속받아 보다 사용하기 편하도록 설계되어진 클래스입니다.


어쨌든 이제 소스상에서 뷰 플리퍼를 동작시켜 보겠습니다.

액티비티 자바 소스를 다음과 같이 편집합니다.


package akj.FlipperEx;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.ViewFlipper;


public class FlipperEx extends Activity implements OnClickListener {

ViewFlipper flipper;

Button buttonNext;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


flipper = (ViewFlipper) findViewById(R.id.viewFlipper_details);

buttonNext = (Button) findViewById(R.id.button_next);

buttonNext.setOnClickListener(this);

}

@Override

public void onClick(View v) {

flipper.showNext();

}

}


소스는 매우 간단합니다.

플리퍼를 findViewById() 메소드를 이용하여 리소스에서 찾아 등록하고

버튼의 리스너에서 단순히 showNext() 를 하면 끝입니다.


결과 화면입니다.


 


 


버튼을 누를때마다 다음 뷰가 나오게 되죠.


이제 조금 더 응용해보겠습니다.

방금 화면에서 시간 간격에 따라 자동으로 화면이 바뀌게 하는 것입니다.

슬라이드 쇼 처럼 말이죠.


이것 역시 매우 간단합니다.

소스를 다음과 같이 수정합니다.


 package akj.FlipperEx;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.ViewFlipper;


public class FlipperEx extends Activity implements OnClickListener {

ViewFlipper flipper;

Button buttonNext;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


flipper = (ViewFlipper) findViewById(R.id.viewFlipper_details);


final int slideTime = 3000;


flipper.setFlipInterval(slideTime);

flipper.startFlipping();


buttonNext = (Button) findViewById(R.id.button_next);

buttonNext.setOnClickListener(this);

}

@Override

public void onClick(View v) {

flipper.showNext();

}

}


굵은 글씨가 소스에서 바뀐 부분입니다.

단지 setFlipInterval() 메소드로 슬라이드할 시간을 설정하고,

startFlipping() 메소드를 호출하면 끝납니다.


이것을 실행하면 화면이 3초마다 자동으로 바뀌게 됩니다.

물론 버튼을 클릭하면 바로 화면이 바뀌게 되죠.


하지만 화면이 그냥 바뀌기 때문에 아무런 감흥도 없습니다.

화면이 바뀔때 애니메이션을 넣는다면 조금 더 그럴싸해 보일것 같습니다.


이번에는 화면이 바뀔때에 애니메이션을 지정해 보겠습니다.


먼저 애니메이션으로 사용할 xml 을 만들어보겠습니다.


res 폴더에 직접 anim 폴더를 생성해서 만들어도 되지만,

eclipse 에서 안드로이드 애니메이션 xml 형식 파일을 지원하므로, 그것을 사용하겠습니다.

 

패키지 익스플로러 창에서 res -> new -> other 를 클릭합니다.

 



Android XML File 을 더블 클릭합니다.

 



타입과 파일 이름을 지정하고 완료합니다.

 



이제 패키지 익스플로러를 가보면 anim 폴더와 xml 파일이 자동으로 생성된 것을 볼 수 있습니다.


in_anim 은 페이지가 새로 들어올때의 애니메이션을 설정하겠습니다.

xml 을 다음과 같이 수정합니다.


in_anim.xml

 ?xml version="1.0" encoding="utf-8"?>

<set

xmlns:android="http://schemas.android.com/apk/res/android">

<translate 

android:fromXDelta="-100%p"

android:toXDelta="0%p"

android:duration="1000">

</translate>

</set>



translate 속성은 뷰를 상하 좌우로 이동 시킬수 있는 애니메이션입니다.

fromXDelta 가 시작점의 X 좌표 이고, toXDelta 목적지의 X 좌표입니다.


-100% 에서 0% 로 온다는 것은 왼쪽끝에서 원래 뷰의 위치로 애니메이션 되는 것을 의미합니다.

duration 속성은 애니메이션이 진행되는 시간을 의미합니다.


또 슬라이드 쇼처럼 보이기 위해서는 현재 뷰가 밖으로 빠져나가는 애니메이션이 있어야 하므로

아웃 애니메이션도 만들겠습니다.


out_anim.xml 파일을 생성하고 다음과 같이 편집합니다.


<?xml version="1.0" encoding="utf-8"?>

<set

xmlns:android="http://schemas.android.com/apk/res/android">

<translate 

android:fromXDelta="0%p"

android:toXDelta="100%p"

android:duration="1000">

</translate>

</set>


in 애니메이션과 다른 부분은 시작위치의 X 좌표와 목적 위치의 Y 좌표 뿐입니다.

0% 인 지금 위치에서 오른쪽 끝인 100% 까지 애니메이션 되는 것이지요.


이제 소스에서 뷰 플리퍼와 애니메이션을 연결하겠습니다.


액티비티 소스를 다음과 같이 수정합니다.


 package akj.FlipperEx;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.animation.AnimationUtils;

import android.widget.Button;

import android.widget.ViewFlipper;


public class FlipperEx extends Activity implements OnClickListener {

ViewFlipper flipper;

Button buttonNext;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


flipper = (ViewFlipper) findViewById(R.id.viewFlipper_details);


final int slideTime = 5000;


flipper.setFlipInterval(slideTime);

flipper.startFlipping();

flipper.setInAnimation(AnimationUtils.loadAnimation(

getApplicationContext(), R.anim.in_anim));

flipper.setOutAnimation(AnimationUtils.loadAnimation(

getApplicationContext(), R.anim.out_anim));


buttonNext = (Button) findViewById(R.id.button_next);

buttonNext.setOnClickListener(this);

}

@Override

public void onClick(View v) {

flipper.showNext();

}

}


역시 굵은 글씨가 바뀐 부분입니다.

단순히 setInAnimation() 메소드와 setOutAnimation() 메소드를 이용하여 애니메이션을 등록하면 됩니다.

AnimationUtils.loadAnimation() 메소드로 리소스의 애니메이션을 가져와서 말이죠.


실행하면 3초마다 애니메이션과 함께 슬라이드 쇼처럼 뷰가 바뀌는 것을 확인 가능합니다.


조금 더 내용을 추가해보겠습니다. 

뷰 플리퍼는 자식 뷰로 레이아웃을 가지는것도 가능합니다.

원래 뷰 플리퍼 자체가 레이아웃을 상속받으므로 당연한 이야기 입니다.


확인해보기 위해 레이아웃 xml 파일을 다음과 같이 수정해보겠습니다.


main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<Button  

android:id="@+id/button_next"

    android:layout_width="fill_parent" 

    android:layout_height="wrap_content" 

    android:text="next view"

    />

<ViewFlipper

android:id="@+id/viewFlipper_details"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical">

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</AnalogClock>

<DigitalClock

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</DigitalClock>

</LinearLayout>

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="first page">

</TextView>

</ViewFlipper>

</LinearLayout>


굵은 글씨가 바뀐 부분입니다. 

뷰 플리퍼에 텍스트 뷰 세 개 대신에 리니어 레이아웃 하나와 텍스트 뷰 하나를 넣었습니다.

소스 수정은 전혀 하지 않아도 됩니다.


실행하면 다음과 같이 됩니다.

 

 

왼쪽 화면에서 오른쪽 화면으로 애니메이션과 함께 5초마다 바뀌게 됩니다.


조금 더 나가서 플리퍼에 등록할 뷰의 개수를 미리 알 수 없을때는 어떻게 해야 할까요.

 동적으로 뷰를 플리퍼에 추가하는 것을 해보겠습니다.


최대한 간단하게 하기 위해, 상단에 버튼대신 텍스트뷰와 에디트 텍스트를 넣고,

버튼을 누르는 경우 에디트 텍스트의 문자열을 읽어와 새로운 텍스트 뷰를 만들어

뷰 플리퍼에 등록해 보겠습니다.


레이아웃 xml 파일을 다음과 같이 수정합니다.


main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

    <LinearLayout

     android:layout_width="fill_parent"

     android:layout_height="wrap_content"

android:orientation="horizontal">

     <Button  

android:id="@+id/button_next"

    android:layout_width="wrap_content" 

    android:layout_height="wrap_content" 

    android:text="Add View"

    />

    <EditText

     android:id="@+id/editText"

     android:layout_width="fill_parent" 

    android:layout_height="wrap_content">

    </EditText>

    </LinearLayout>

<ViewFlipper

android:id="@+id/viewFlipper_details"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical">

<AnalogClock

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</AnalogClock>

<DigitalClock

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</DigitalClock>

</LinearLayout>

<TextView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="first page">

</TextView>

</ViewFlipper>

</LinearLayout>


역시 굵은 글씨가 바뀐 부분입니다.

버튼 대신에 리니어 레이아웃을 넣고 버튼과 에디트텍스트 위젯을 가로로 배치했습니다.


이제 버튼에 리스너에서 에디트 텍스트의 내용을 읽어 새로운 뷰를 플리퍼에 등록해보겠습니다.


소스를 다음과 같이 수정합니다.

package akj.FlipperEx;


import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup.LayoutParams;

import android.view.animation.AnimationUtils;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

import android.widget.ViewFlipper;


public class FlipperEx extends Activity implements OnClickListener {

ViewFlipper flipper;

Button buttonNext;

EditText editText;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);


flipper = (ViewFlipper) findViewById(R.id.viewFlipper_details);


final int slideTime = 5000;


flipper.setFlipInterval(slideTime);

flipper.startFlipping();

flipper.setInAnimation(AnimationUtils.loadAnimation(

getApplicationContext(), R.anim.in_anim));

flipper.setOutAnimation(AnimationUtils.loadAnimation(

getApplicationContext(), R.anim.out_anim));


buttonNext = (Button) findViewById(R.id.button_next);

buttonNext.setOnClickListener(this);

editText = (EditText) findViewById(R.id.editText);

}

@Override

public void onClick(View v) {

String text = editText.getText().toString();


if (text.length() == 0) {

return;

}


TextView tv = new TextView(getApplicationContext());

tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,

LayoutParams.FILL_PARENT));

tv.setText(text);

flipper.addView(tv);

}

}


역시 굵은 글씨가 바뀐 부분입니다.

실행하면 처음에는 두개의 뷰가 애니메이션 되지만

에디트텍스트에 내용을 입력하고 addView 버튼을 누르면 

해당 텍스트를 지닌 텍스트뷰가 추가되어 애니메이션 되는것을 확인할 수 있습니다.


 



비슷한 방법으로 갤러리에서 이미지를 동적으로 불러와 슬라이드 하는등

여러가지 응용이 가능합니다.

728x90
Posted by 정망스
,
728x90

나는 안드로이드 정말 초짜다, 정말 모르는 사람이다. 나의 공부자료들을 보고 내가 어느정도 공부했고 좀 아는사람이다 라고는

착각하지 말아주시길... 가끔 질문겸 글들을 보내오시는데 저도 정말 잘 몰라요.....


본론으로 들어가서 이 글은 다른 블로거님께서 잘 정리 해놓으신걸 바탕으로 요약해서 쓴다.


나의 폰으로 테스트 앱을 실행해보고 잇던중 EditText에 한글을 입력하려하는데 한글이 입력되지 않았다.

자꾸 한글자판 위치에 맞는 영어가 출력되어 나왔다.


소프트 키패드를 쿼티(Qwerty) 키패드로 사용하고 있었는데 이것이 문제였다. 보이기는 한글 자판인데 영문이 입력되는 것이였다.

대충 지금 쿼티로 사용할경우 안되는 단말기는 갤럭시 넥서스, 갤럭시s2, 갤럭시s, 갤럭시 노트, 갤럭시 노트2 정도라고 한다.


android:inputType="textVisiblePassword" or "text" 줄경우에 안되는것을 확인했다고 한다.

아무것도 주지 않을때는 입력이 되었다고 한다.


아무것도 안주면 기본적으로 쿼티 키패드의 모든 문자형식을 다 사용할 수 있다라고 한다.


728x90
Posted by 정망스
,
728x90

TextWatcher를 선언하면 아래 메서드들을 @Override 할수 있다.

 

@Override

public void onTextChanged(CharSequence s, int start, int before, int count)

 

s : 현재 입력이 수행되고 있는 문자열.

start : 변경이 문자열의 어느 위치에서 수행되었는지 문자열 인덱스로 알려줌.

before : 변경이 수행되기 전 해당 위치의 문자열 길이를 나타냄.

count : 변경이 수행된 문자열의 개수

 

이 메소드는 s가 변경될 때 호출된다,

 

 

 

 ㅊ

처 

청 

청ㄷ 

청다 

청담 

청담ㄷ 

청담도 

청담동 

 start

0  1 

1

1  2

 before

1  0 

1  0 

 count

1  1 

1  1 

 

최종적으로 문자열은 s[0]=청, s[1]=담, s[2]=동 이렇게 저장된다.

변수값의 변화에서 "청ㄷ", 또는 "청담ㄷ" 와 같이 새로 글자가 시작될때는 onTextChanged가 두 번 각기 다른 매개변수값들로 호출된다.

(현재 완성된 글자의 위치에서 일단 시작, "처"와 같은 글자는 한번에서 글자에 따라서는 두번의 입력을 현재 위치에서 받아서 "청" 이 될 수 있다. 하지만 "청"은 다음 입력을 받을 수 없다. 그래서 그 다음 입력은 s의 다음 칸에 할당이 되어야 한다. 이런 과정으로 인해 onTextChanged도 역시 두 번 호출되게 된다.)

 

@Override
public void beforeTextChanged(CharSequence s, int start, int before, int count)

 

앞서 onTextChanged와 개념은 똑같은듯 하다.

s는 텍스트 변화가 있기전의 값이라 생각하면 되겠다.

 

@Override
public void afterTextChanged(Editable s)

 

s는 텍스트 변화가 있기전의 값이다.

 

728x90
Posted by 정망스
,
728x90

노트북에 안드로이드 환경을 구축하려 시도를 했다. 결론은 이클립스 안드로이드 환경 구축하는데 하루가 걸렸다..(삽질..)

 

최근 안드로이드 배포가 많이 바뀐것 같았다.

아예 최신 SDK까지 포함한채로 이클립스 압축파일을 배포하고있었다.

 

하지만 난 그것을 원한게 아니라

주로 웹 개발을 목적으로 이클립스 ee버전을 사용하고있기 때문에 지금 사용하는 이클립스 자체에 안드로이드를 설치하고싶었다.

 

예전방식대로 안드로이드 구글 주소와함께 ADT를 설치하고 했는데

왜냐...

왜 이 아이콘들이 보이지 않느냐...

많은 고심을 하다가 아 ... 삽질했구나.... 퍼스펙티브를 java로 바꾸니 이 아이콘이 보였다...(....................)

 

이제 다른 하위 sdk 버전들을 다운받자 라는생각에 SDK Manager를 실행했는데 뭐냐

sdk manager 경로를 계속찾을수 없단다

난 분명 경로설정 되있는데 말이다....

 

고심끝에 구글링을하던중 발견!

 

나만 이런것이 아니였다. 윈도우8에서만 이런건지는 모르겠는데 jdk의 경로명에 포함되어있는 띄어쓰기를 인식하지못해 실행이 안되고 있었다.

 

 

이것은 나의 컴퓨터 윈도우7환경의 경로인데 띄어쓰기 있는데도 잘 인식한다..

 

그런데 이상하게 윈도우8 노트북에서만 안된다.

 

그래서 기존 jdk를 지우고 다시 설치하되, 경로명에 띄어쓰기 없는 경로에 설치했다

나같은경우엔 c안에 위치한 temp폴더에 java폴더를 생성해서 설치했다

 

그랬더니 SDK Manager이 아주 잘실행 된다~

728x90
Posted by 정망스
,
728x90

추가되는 과정

1.사용자가 텍스트를 입력한다.

2.추가 버튼을 누른다

2-1.문자열이 데이터 부분에 저장된다.

2-2.변경된 문자열이 있음을 어댑터가 알고 리스트 뷰한테 변경된 데이터의 값을 알림과 동시에 값을 바뀌게 하게끔 알린다.

3.문자열을 리스트뷰에 보여준다.

 

2-1 : 자바 코드상에 선언된 ArrayList에 추가한다

2-2 : adapter.notifyDataSetChanged();

 

main.xml

ListViewTestActivity01.java

붉게 표시된 부분이 중요 코드 이며

데이터에 추가하고 어댑터가 리스트 뷰한테 알려주는 과정이다

다만 notifyDataSetChanged()라는 메소드가 리스트뷰 갱신을 위하여 쓰여진다 라는 정도만 알고 가면 좋다.

 

위의 코드에서 파란색으로 표시된 부분은  항상 같이 따라 다녀야 한다. 

android.R.layout.simple_list_item_single_choice 

--> 리스트뷰 모양을 우측에 라디오 버튼을 추가해서 선택할 수 있도록 해라.


list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

--> 리스트뷰를 한개 선택할 수 있도록 해라.


보이는 것처럼 위의 두녀석은 항상 붙어 다닌다. 뷰 모양은 1개 선택인데 리스트뷰의 선택모드는 선택안됨으로 되어 있으면 말이 안되지만

그렇다고 에러는 나지 않는다. 다만 그에 따라 선택이 되지 않을 뿐 이다.

 

삭제하는 과정

1.리스트 뷰에서 여러개를 선택한다.

1.1 여러개를 선택해야 하므로 리스트뷰의 레이아웃은 android.R.layout.simple_list_item_multiple_choice

1.2 여러개가 선택되어야 하므로 리스트 뷰의 모드는 setChoiceMode(ListView.CHOICE_MODE_MULTIPLE)

2.삭제 버튼을 누른다.

3.선택된 녀석들을 가지고 와서 데이터에서 삭제한다.

4.리스트 뷰를 갱신한다.

 

main.xml

ListViewTestActivity02.java

첫 예제와 거의 동일하지만 붉은 표시 코드 부분만 다르게 작성되어잇는걸 알수 있다.

mAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice, dataArr);

list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

가장 먼저 하여야한다 여러개를 선택해야 하므로 뷰의 레이아웃과 모드를 모두 변경 시켜 주어야지만 반영이 된다.

반드시 같이 움직인다는것도 잊지 말아야 한다.

 

SparseBooleanArray checkArr = list.getCheckedItemPositions();

if (checkArr.size() != 0) {

     for (int i = list.getCount() -1; i > -1 ; i--) {

          if (checkArr.get(i)) {

               dataArr.remove(i);

          }

             }

}

1.첫번째 다중선택시 리스트로부터 받아오는 값은 선택된 SparseBooleanArray 형태의 객체이다.

boolean형태의 배열이 아닌 객체 형태 이다. ArrayList와 비슷하고. 리스트뷰의 모든 값을 저장하고 있으며 선택되었으면 해당위치가 true, 선택되지 않았다면 해당위치는 false로 저장되어 있다. 그러니 루프문을 돌면서 checkArr.get(i) 가 참이면 선택되었다. 라는 뜻이므로 해당 위치는 삭제를 하면 된다.

 

2. 여러개의 데이터를 삭제할때는 처음부터가 아닌 반드시 꼭 마지막 부터 삭제하라.

첫번째 데이터인 0번부터 삭제를 하면 문제가 발생할때가 있다.

 

0번(1) 2번(3)순으로 삭제 하기를 원한다면

 

 

결과가 다르게 나와 버린다.

그래서 뒤에서 부터 삭제하는 것을 권장한다.

 

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침