2010년/완전정복
6장 메뉴
뽀얀햄스터
2011. 2. 28. 18:01
안드로이드 지원하는 메뉴는 3가지
옵션 메뉴, 컨텍스트 메뉴,서브 메뉴
옵션 메뉴 : 액티비티의 주메뉴이며 평소에는 평소에 화면 아래쪽에 숨겨져 있으며 MENU 버튼을 눌러야함
컨텍스트 메뉴 : 화면을 일정한 시간 동안 누르고 있으면 화면 중앙에 나타난다. 주로 리스트 뷰의 항목에 대해 사용되지만 임의의 위젯에 대해서도 사용할 수 있다.
서브 메뉴 : 메뉴 항목을 가지는 일종의 팝업이며 화면 한 가운데에 나타난다.
public class OptionMenu extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView MyText = new TextView(this);
MyText.setText("메뉴 키를 누르세요.");
setContentView(MyText);
}
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuItem item=menu.add(0,1,0,"짜장");
item.setIcon(R.drawable.icon);
item.setAlphabeticShortcut('a');
//menu.add(0,1,0,"짜장").setIcon(R.drawable.icon).setAlphabeticShortcut('a');
menu.add(0,2,0,"짬뽕").setIcon(R.drawable.icon);
SubMenu etc = menu.addSubMenu("기타");
etc.add(0,3,0,"우동");
etc.add(0,4,0,"만두");
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
Toast.makeText(this,"짜장은 달콤해",Toast.LENGTH_SHORT).show();
return true;
case 2:
Toast.makeText(this,"짬뽕은 매워",Toast.LENGTH_SHORT).show();
return true;
case 3:
Toast.makeText(this,"우동은 시원해",Toast.LENGTH_SHORT).show();
return true;
case 4:
Toast.makeText(this,"만두는 공짜야",Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}
여기서 사실 중요한것은 그다지 없다 한번 보면 이해는 된다.
다만 많이 사용해서 익숙한지 아닌지에 대해서 차이다.
많이 사용하게 된다면 당연히 숙지가 가능하지만 한번보고 넘어간다면 사실 이해하기 힘들다.
public boolean onCreateOptionsMenu(Menu menu) 인수로 빈 메뉴 객체인 menu에 전달이 되며 메뉴항목이 여기에 추가가 된다. 메뉴항목을 추가 할시에는
menu.add(0,1,0,"짜장"); 통해서 add가 된다. 그리고 .setIconR.drawable.icon); 통해서 아이콘 모양을 지정이 가능하고
.setAlphabeticShortcut('a'); 통해서 단축키도 지정이 가능하다.
SubMenu etc = menu.addSubMenu("기타"); 통해서 Sub메뉴를 만들고 만들어지 서브메뉴에 다시 etc.add할수 있다.
public boolean onOptionsItemSelected(MenuItem item)를 통해서 옵션메뉴가 선택되었을때 동작상태를 알수 있다.
switch (item.getItemId())로 add할때 itemId를 통해서 할수있다.
XML로 메뉴 정하기
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/jjajang"
android:title="짜장"
android:icon="@drawable/icon"
android:alphabeticShortcut="a"
/>
<item android:id="@+id/jjambbong"
android:title="짬뽕"
android:icon="@drawable/icon"
/>
<item android:id="@+id/submenu"
android:title="기타">
<menu>
<item android:id="@+id/udong"
android:title="우동"
/>
<item android:id="@+id/mandoo"
android:title="만두"
/>
</menu>
</item>
</menu>
아까 위에 소스는 JAVA에서 구현을 했다. 하지만 만약 우리나라가 아닌 다른나라 모든 나라에서 사용한다면 언어의인코딩에 관해서 문제가 생긴다. 그래서 XML을 통해서 메뉴를 만드는것은 권장한다.
XML에서 메뉴와 대응하는것은 <item> 엘리먼트이다. 그리고 <item>안에 <menu>로 인해 서브 메뉴까지 지정해줄수 있다.
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class OptionMenu2 extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView MyText = new TextView(this);
MyText.setText("메뉴 키를 누르세요.");
setContentView(MyText);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu,menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.jjajang:
Toast.makeText(this,"짜장은 달콤해",Toast.LENGTH_SHORT).show();
return true;
case R.id.jjambbong:
Toast.makeText(this,"짬뽕은 매워",Toast.LENGTH_SHORT).show();
return true;
case R.id.udong:
Toast.makeText(this,"우동은 시원해",Toast.LENGTH_SHORT).show();
return true;
case R.id.mandoo:
Toast.makeText(this,"만두는 공짜야",Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu,menu);
차이점이라곤 딱하나 있다. XML를 가져오기위해서 MenuInflater를 사용했다는 점
MenuInflater 클래스에 대한내용이다 만들그대로 XML파일중 Menu객체를 가져와서 사용한다.
그리고 생성자로 MenuInflater(Context context)를 사용해도 되지만 마찬가지로
getMenuInflater()이용해서 XML Menu객체를 가져온다.
사용 메서드는 간단하게 딱하나있다. 바로 inflate()를 메뉴가 들어있는 리소스를 가져온다.
XML 파일을 가져오는 LayoutInflate도있다.
체크 메뉴 항목
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/submenu"
android:title="Sub Menu">
<menu>
<group android:id="@+id/checkable_group"
android:checkableBehavior="all">
<item android:id="@+id/bigfont"
android:title="BigFont"
android:checked="false" />
</group>
<group android:id="@+id/exclusive_checkable_group"
android:checkableBehavior="single">
<item android:id="@+id/red"
android:title="Red"
android:checked="true" />
<item android:id="@+id/green"
android:title="Green" />
<item android:id="@+id/blue"
android:title="Blue" />
</group>
</menu>
</item>
</menu>
XML에서 <item>, <menu> 서브메뉴로 만들었다. 그리고 서브메뉴를 그룹을 2개를 만들었고
하나는 CheckableBehavior="all" 사각형 모양의 체크박스가 표시된다.
나머지 하나는 single로 그룹에 속한 항목중 하나만 선택할수있게 했다.
import android.app.*;
import android.graphics.*;
import android.os.*;
import android.view.*;
import android.widget.*;
public class MenuCheck extends Activity {
Button mBtn;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menucheck);
mBtn = (Button)findViewById(R.id.button);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menucheck,menu);
return true;
}
public boolean onPrepareOptionsMenu(Menu menu) {
if (mBtn.getTextSize() == 40) {
menu.findItem(R.id.bigfont).setChecked(true);
} else {
menu.findItem(R.id.bigfont).setChecked(false);
}
int color = mBtn.getTextColors().getDefaultColor();
if (color == Color.RED) {
menu.findItem(R.id.red).setChecked(true);
}
if (color == Color.GREEN) {
menu.findItem(R.id.green).setChecked(true);
}
if (color == Color.BLUE) {
menu.findItem(R.id.blue).setChecked(true);
}
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.bigfont:
if (item.isChecked()) {
mBtn.setTextSize(20);
} else {
mBtn.setTextSize(40);
}
return true;
case R.id.red:
mBtn.setTextColor(Color.RED);
return true;
case R.id.green:
mBtn.setTextColor(Color.GREEN);
return true;
case R.id.blue:
mBtn.setTextColor(Color.BLUE);
return true;
}
return false;
}
}
===========================================================================================
public boolean onCreateOptionsMenu
public boolean onPrepareOptionsMenu
두 OptionMenu 약간차이점이 있다 옵션 메뉴가 처음만들어질때 onCreateOptionMenu를 사용한다. 하지만 처음 만들어짐으로 메뉴의 내용이 변경이될때 수정할수가 없다. 그래서 사용하는것이 onPrepareOptionMenu이다. check box에서 check가 자주 변경된다. 이렇게 메뉴가 내용이 수정될때는 onPrepareOptionMenu를 사용한다.
컨텍스트 메뉴
특정 뷰나 항목에 필요한 명령들만 모아놓은 메뉴이다.
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.os.*;
import android.util.*;
import android.view.*;
import android.widget.*;
public class ContextMenuTest extends Activity {
Button mBtn;
EditText mEdit;
MyImage mImage;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contextmenu);
// long 클릭했을때 버튼과 실행하는 방법
mBtn = (Button)findViewById(R.id.button);
// registerForContextMenu(mBtn);
mEdit = (EditText)findViewById(R.id.edittext);
registerForContextMenu(mEdit);
mImage = (MyImage)findViewById(R.id.myimage);
registerForContextMenu(mImage);
//한번 클릭했을때 Context메뉴가 실행되게 한방법.
mBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
// v에 ContextMenu를 assign
registerForContextMenu( v );
// ContextMenu를 바로 출력
openContextMenu( v );
// ContextMenu 헤제
unregisterForContextMenu( v );
}
});
}
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v == mBtn) {
menu.setHeaderTitle("Button Menu");
menu.add(0,1,0,"Red");
menu.add(0,2,0,"Green");
menu.add(0,3,0,"Blue");
}
if (v == mEdit) {
menu.add(0,4,0,"번역하기");
menu.add(0,5,0,"필기 인식");
}
}
public boolean onContextItemSelected (MenuItem item) {
switch (item.getItemId()) {
case 1:
mBtn.setTextColor(Color.RED);
return true;
case 2:
mBtn.setTextColor(Color.GREEN);
return true;
case 3:
mBtn.setTextColor(Color.BLUE);
return true;
case 4:
Toast.makeText(this,"번역했다.",Toast.LENGTH_SHORT).show();
return true;
case 5:
Toast.makeText(this,"필기 인식했다.",Toast.LENGTH_SHORT).show();
return true;
case 100:
Toast.makeText(this,"회전했다 치고.",Toast.LENGTH_SHORT).show();
return true;
case 101:
Toast.makeText(this,"크기 변경 했다 치고.",Toast.LENGTH_SHORT).show();
return true;
}
return true;
}
}
class MyImage extends ImageView {
public MyImage(Context context) {
super(context);
}
public MyImage(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
menu.setHeaderTitle("MyImage Menu");
menu.add(0,100,0,"이미지 회전");
menu.add(0,101,0,"크기 변경");
}
}
===================================================================
registerForContextMenu(View)
안드로이드에서 에디트 뷰에서 롱키를 눌릴경우 컨텍스트 메뉴가 디폴트것이 열린다. 그안에는 copy all, paste등 여러가지가있다.
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
선언을 해줘야 당연히 위에 롱키에 관해서 사용할수가 있다.
원래 소스는 롱키에 관해서이다.
하지만 이 컨텍스트 메뉴를 원클릭으로도 사용할수 있다.
mBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
// v에 ContextMenu를 assign
registerForContextMenu( v );
// ContextMenu를 바로 출력
openContextMenu( v );
// ContextMenu 헤제
unregisterForContextMenu( v );
}
});
버튼을 onClickListener에 넣은다음.. registerForContextMenu();를 통해서 실행시킨다음 openContextMenu(v);로 바로 출력시킨다. 그리고 unregisterForContextMenu( v );를 통해서 해제한다.
마지막으로 대충 디버깅에 대해서 알아보자.
Visual studio 같은경우 break point를 잡아서 한다. 단축키가 F9이다. 하지만 이클립스같은경우는 조금 틀리다. 사실 잘몰랐는데 이번 기회에 조금 알게 되었다.
뭐 break point 역시 찍을수 있다 파란색으로 너무 작게 나와서.. 잘안보인다
단축키는 Ctrl+Shift+B이다. 간단하게 F9하면 쉬운데 ㅠ
F11을 통해서 실행시키자
실행된 기억력 게임에서 도형이 아닌 빈곳을 클릭한다.
그러면 대화상자가 하나뜬다.
당연히 Yes를 눌리고 디버깅모드로 가야한다.
디버그 화면은 visual때와 비슷하다
값이 있는 부분 그리고 breakpoint부분 디버그에서 쓰레드와 달빅에서 메모리까지 넘어가는 부분 breakpoint를 잡은 소스 부분까지 비슷하다.
Variables 값을 볼수 있으면 마우스 오른쪽 버튼으로 watch를 통해서 특정 값의 상태도 알수 있다.
그리고 디버깅에서 단축키는.
F5 메서드 안으로 추적해 들어간다.
F6 다음 명령문을 실행한다.
F7 메서드의 끝까지 실행하고 리턴한다.
F8 다음 중단점까지 실행한다.
Ctrl+R 커서가 있는 지점까지 실행한다.
Ctrl + F2 디버깅을 중단한다.
이렇게 되어있다.
아까 실행화면에서 빈곳을 찍었다. 즉 터치를 했고
터치하는 부분을 breakpoint로 잡았다.
그래서 sel이라는 값이 변경된다.
sel값이 -1로 나타있다
이런식으로 값을 확인하면서 디버깅을 할수있다.
개인적으로 실무에서는 개발도 중요하지만 디버깅도 중요하다고 생각하기에 크다고 본다.