안드로이드 휴대폰 상에 실제 mm 계산하기(dpi를 mm으로 바꾸기)

 

블로그 초기에 안드로이드에서 쓰이는 길이 단위에 대해서 알아보았습니다.

안드로이드에서 쓰이는 길이 단위(dp,sp,pt,px,mm,in)

 

제가 길이 단위에 대해서 알아본 것은

결과적으로 휴대폰의 클릭하는 지점의 좌표를 mm로 알아내려고 한 것이었습니다.

 

방법은 간단합니다.

 

휴대폰에서는 모든 좌표를 px단위로 받습니다.

그리고 dpi=px/inch이므로,

mm=px*25.4/dpi로 변환이 가능합니다.

 

그러므로, 좌표를 px단위로 입력 받은 뒤에, mm로 변환하면 됩니다.

 

        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
        
        xdpi=outMetrics.xdpi;//x방향 dpi
        ydpi=outMetrics.ydpi;//y방향 dpi

 

로 각 방향의 dpi를 받은 뒤,

mm=px*25.4/dpi

식에 대입하여 전환하면 오케이!!

Posted by 90002

다이얼로그 새로 고침. 매번 같은 내용 나올 때

 

커스텀 다이얼로그를 사용하다보면,

안의 내용을 바꿔도 다이얼로그가 변하지 않는 경우가 있습니다.

방법은 간단합니다.

 

 @Override
   protected void onPrepareDialog(int id, Dialog dialog, Bundle args){
    super.onPrepareDialog(id, dialog,args);
     //다이얼로그 불릴때마다 초기화
    removeDialog(id);

  }

 

를 하면 됩니다. 여기서 id는 showDialog(id)에 넣었던 id를 넣으면 됩니다^^

Posted by 90002

커스텀 다이얼로그를 하면 버튼을 눌러도 닫기가 되지 않습니다.

이것을 해결하기 위한 방법으로는 세가지가 있습니다.

 

1. 커스텀 다이얼로그를 Class로 만들어서 사용하기

 

첫번째 방법으로는 커스텀 다이얼로그를 아예 따로 Class를 만들어서 사용하는 방법입니다.

 

//CustomizeDialog.java-텍스트뷰와 Close 버튼만 있습니다.

public class CustomizeDialog extends Dialog implements OnClickListener {
Button close;
TextView tv;
public CustomizeDialog(Context context,String Stringcontent) {
   
super(context);
    requestWindowFeature
(Window.FEATURE_NO_TITLE);     
    setContentView
(R.layout.custom_diolog_main);
    tv
=(TextView) findViewById(R.id.content);
    tv
.setText(Stringcontent);
    close
= (Button) findViewById(R.id.close);
    close
.setOnClickListener(this);
}

@Override
public void onClick(View v) {      
   
if (v == close)
        dismiss
();
}
}

 

부를 때는 다음과 같이 하면 됩니다.

CustomizeDialog customizeDialog = new CustomizeDialog(CustomDialog.this,"clickme");
customizeDialog.show();
출처 :http://stackoverflow.com/questions/8736508/android-close-custom-dialog-within-layout
2. Dialog 클래스를 선언해서 사용하기
개인적으로는 훨씬 쉬운 방법이라고 생각합니다!
AlertDialog.Builder CustomizeDialog = new AlertDialog.Builder(CompareSizeCore.this)
.setView(CustomizeView)
.create();
등과 같이 커스텀 다이얼로그를 선언(?), 변수화?음... 어쨋든 위와 같이 하고,
닫고 싶은 위치에서는
 CustomizeDialog.dismiss(); 
하면 닫을 수 있습니다!!
 
3. dissmissDialog(id) 사용하기
id에는 showDialog(id)에 적었던 id를 적으면 됩니다.
Posted by 90002
인텐트를 다루는 두 번째 시간이 돌아왔습니다. (와우!)
이번 강좌는 저도 인텐트를 쪼~까 공부하느라 뭔가 깔끔하지 못할 지도 모르겠네요(...)
그래도 최대한 자세하게 다뤄보도록 할테니! 걱정은 마시고!! 따라오시면 될겁니다. (아마도요...펑...)

지난 시간에는 다른 액티비티를 단순히 "호출"하는 것만 배웠습니다. 그런데, 실제 어플리케이션을 개발하다보면 액티비티를 호출하는 것은 어찌보면 당연한 것이고, 액티비티간에 데이터를 주고받아야 할 일이 생깁니다. 그럴 땐 어떻게 해야 할까요? => 바로, 이 때도 인텐트를 사용하면 됩니다(...)

인텐트는, 액티비티를 호출하는 수단 뿐 아니라 인텐트 자체에 액티비티간 주고받아야 할 정보들을 실어줄 수 있습니다. 예를 들자면 심부름꾼(???) 이라고 할까나요??

A라는 사람이 B에게 물건을 가져오라고 심부름꾼에게 시키면, 심부름꾼은 B에게 가서 물건을 받아 A에게 전달해주게 됩니다. 마찬가지로, 액티비티 A가 B로부터 어떠한 정보를 받고 싶다면, 인텐트를 사용하여 B를 호출한 다음, 인텐트에 원하는 정보를 실어서 그 정보를 다시 돌려받으면 됩니다.

일단, 호출하는 액티비티 (InformationInput)호출당하는 액티비티(InformationProc)의 코드를 보도록 하겠습니다.


(주의)
액티비티를 추가하는 방법을 모르신다면, 2009/03/01 - [안드로이드/안드로이드 입문] - [강좌] [수정] 이클립스에서 안드로이드 액티비티 추가하기 를 읽고 액티비티 추가 방법에 대해 숙지하신 후 이 강좌를 읽어주세요.


[InformationInput.java]

01.package com.androidhuman.IntentTest;
02.import android.app.Activity;
03.import android.content.Intent;
04.import android.os.Bundle;
05.import android.view.View;
06.import android.widget.Button;
07.import android.widget.TextView;
08.
09.public class InformationInput extends Activity {
10. /** Called when the activity is first created. */
11. @Override public void onCreate(Bundle savedInstanceState) {
12. super.onCreate(savedInstanceState);
13. setContentView(R.layout.main);
14. final Button requestInfo = (Button)findViewById(R.id.requestInfo);
15. requestInfo.setOnClickListener(new Button.OnClickListener(){ // 버튼을 클릭할 경우
16. public void onClick(View v){
17. Intent intent = new Intent(InformationInput.this,InformationProc.class);
18. startActivityForResult(intent, 1); // Sub_Activity 호출
19. }
20. });
21. }
22.
23. @Override
24. protected void onActivityResult(int requestCode, int resultCode, Intent data){
25. super.onActivityResult(requestCode, resultCode, data);
26. TextView name_view = (TextView)findViewById(R.id.name_view);
27. TextView digit_view = (TextView)findViewById(R.id.digit_view);
28. if(resultCode==RESULT_OK) // 액티비티가 정상적으로 종료되었을 경우
29. {
30. if(requestCode==1) // InformationInput에서 호출한 경우에만 처리합니다.
31. { // 받아온 이름과 전화번호를 InformationInput 액티비티에 표시합니다.
32. name_view.setText(data.getStringExtra("data_name"));
33. digit_view.setText(data.getStringExtra("data_digit"));
34. }
35. }
36. }
37. }


[main.xml]
01.<?xml version="1.0" encoding="utf-8"?>
02.<LinearLayout
03.android:layout_height="fill_parent"
04.android:layout_width="fill_parent"
05.android:orientation="vertical"
07.<TextView android:layout_height="wrap_content"
08.android:layout_width="fill_parent"
09.android:text="@string/name" />
10.<TextView android:layout_height="wrap_content"
11. android:layout_width="fill_parent"
12. android:text="-이름이 입력되지 않음-"
13. android:id="@+id/name_view"/>
14.
15.<TextView android:layout_height="wrap_content"
16. android:layout_width="fill_parent"
17. android:text="@string/digit"/>
18.
19.<TextView android:layout_height="wrap_content"
20. android:layout_width="fill_parent"
21. android:text="-전화번호가 입력되지 않음-"
22. android:id="@+id/digit_view"/>
23.
24.<Button android:layout_height="wrap_content"
25. android:layout_width="wrap_content"
26. android:text="@string/button_launch"
27. android:id="@+id/requestInfo"
28. android:layout_gravity="center_horizontal"/>
29.</LinearLayout>



[InformationProc.java]

01.package com.androidhuman.IntentTest;
02.import android.app.Activity;
03.import android.content.Intent;
04.import android.os.Bundle;
05.import android.view.View;
06.import android.view.View.OnClickListener;
07.import android.widget.Button;
08.import android.widget.EditText;
09.public class InformationProc extends Activity {
10. /** Called when the activity is first created. */
11. @Override public void onCreate(Bundle savedInstanceState) {
12. super.onCreate(savedInstanceState);
13. setContentView(R.layout.informationproc);
14. Button input_info = (Button)findViewById(R.id.inputinfo);
15. input_info.setOnClickListener(new OnClickListener(){
16.
17. public void onClick(View v) { //버튼을 클릭하면
18. Intent intent = getIntent(); // 이 액티비티를 시작하게 한 인텐트를 호출
19. EditText name_input = (EditText)findViewById(R.id.name_input);
20. EditText digit_input = (EditText)findViewById(R.id.digit_input);
21. intent.putExtra("data_name",name_input.getText().toString());
22. intent.putExtra("data_digit", digit_input.getText().toString());
23. setResult(RESULT_OK,intent); // 추가 정보를 넣은 후 다시 인텐트를 반환합니다.
24. finish(); // 액티비티 종료
25. }
26. });
27. }



[informationproc.xml]




01.<?xml version="1.0" encoding="UTF-8"?>
02.<LinearLayout
03. android:layout_height="wrap_content"
04. android:layout_width="fill_parent"
05. android:orientation="vertical"
07. android:id="@+id/overview_layout">
08.
09.<TextView android:layout_height="wrap_content"
10. android:layout_width="wrap_content"
11. android:text="@string/text_information"/>
12.
13.<LinearLayout android:layout_height="wrap_content"
14. android:layout_width="fill_parent"
15. android:orientation="horizontal"
16. android:id="@+id/name_layout">
17.
18.<TextView android:layout_height="wrap_content"
19. android:layout_width="wrap_content"
20. android:text="@string/name"/>
21.
22.<EditText android:layout_height="wrap_content"
23. android:layout_width="fill_parent"
24. android:id="@+id/name_input"
25. android:hint="ex)안드로이드"/>
26.</LinearLayout>
27.
28.<LinearLayout android:layout_height="wrap_content"
29. android:layout_width="fill_parent"
30. android:orientation="horizontal"
31. android:id="@+id/digit_layout">
32.
33.<TextView android:layout_height="wrap_content"
34. android:layout_width="wrap_content"
35. android:text="@string/digit"/>
36.
37.<EditText android:layout_height="wrap_content"
38. android:layout_width="fill_parent"
39. android:id="@+id/digit_input"
40. android:hint="ex)011-123-4567"/>
41.
42.</LinearLayout>
43.
44.<Button android:layout_height="wrap_content"
45. android:layout_width="wrap_content"
46. android:text="@string/input"
47. android:id="@+id/inputinfo"
48. android:layout_gravity="center_horizontal"/>
49.</LinearLayout>


단순히 액티비티를 호출할 때에는 startActivity(Intent)를 사용했었지만, 액티비티를 호출한 후 결과값을 받기 위해서는 다른 메소드를 사용해야 합니다. 바로 startActivityForResult(Intent intent, int requestCode)입니다.


public void startActivityForResult(Intent intent, int requestCode)
호출당하는 액티비티로부터 데이터를 넘겨받기 위해 사용합니다.
intent - 인텐트
requestCode - 이 액티비티를 호출하는 액티비티가 여러 개가 있을 경우, 어떤 액티비티가 호출했는지를 알기 위해 사용


requestCode는 별로 특이한 것은 아니고, 한 액티비티를 여러 액티비티가 호출해야 할 경우, 호출이 어디에서 일어났는지를 알려주는 인자값입니다.
일단, InformationInput 액티비티를 봅시다. 버튼을 클릭하면 InformationInput 액티비티가 InformationProc 액티비티를 호출해야 하므로, 일단 intent를 생성하고, startActivityForResult()를 통해 InformationProc 액티비티를 실행시킵니다.



InformationProc 액티비티가 실행되면, 사용자로부터 이름과 전화번호를 입력받게 됩니다.
입력이 끝나고, 입력 버튼을 누르면, 입력받은 데이터를 인텐트에 집어넣게 됩니다.
1.Intent intent = getIntent(); // 이 액티비티를 시작하게 한 인텐트를 호출
2. EditText name_input = (EditText)findViewById(R.id.name_input);
3. EditText digit_input = (EditText)findViewById(R.id.digit_input);
4. intent.putExtra("data_name",name_input.getText().toString());
5. intent.putExtra("data_digit", digit_input.getText().toString());
6. setResult(RESULT_OK,intent); // 추가 정보를 넣은 후 다시 인텐트를 반환합니다.
7.finish(); // 액티비티 종료

차근차근 하나씩 보도록 하겠습니다.
일단, 첫번째, 인텐트를 생성하는 것을 볼 수 있습니다. 보통, 인텐트를 생성할 때 new 생성자를 써서 인텐트를 생성했던 것에 반해, 여기에서는 getIntent()를 사용하여 인텐트를 불러오고 있습니다. getIntent()메소드는 현재 자신을 호출했던 인텐트를 반환해줍니다.

여기서, 자신을 호출한 인텐트를 받아오는 것은, 아까 예로 들었던 심부를꾼을 생각해보면 쉽게 이해할 수 있습니다. A라는 심부름꾼에게서 물건을 받았는데, B라는 심부름꾼에게 물건을 주면 안되겠죠? 인텐트도 마찬가지입니다. :)

이렇게 해서 인텐트를 생성하면, 이제 EditText로부터 입력한 값들을 받아와야 합니다. findViewById()를 이용하여 레이아웃 객체와 코드상의 객체를 연결한 후, putExtra()메소드를 이용해 정보를 실어줍니다.

intent.putExtra(String name, _value)
name이라는 이름을 가지는 데이터를 인텐트에 첨가합니다.

인텐트에 들어가는 데이터는 "키"의 역할을 하는 name과 그에 해당하는 값인 _value가 짝을 이루어 저장됩니다.
이렇게 저장이 되었다면, 호출된 액티비티가 정상적으로 끝났는지, 비정상적으로 끝났는지 (물건을 제데로 받았는지, 심부름꾼이 왔는지 등등...으로 비유할 수 있겠습니다) 자신을 호출한 액티비티에게 알려주기도 해야 하고, 요청한 데이터도 같이 주어야 합니다.

일단, 호출당한 액티비티가 정상적으로 끝났음을 알리기 위해, setResult(RESULT_OK, intent) 메소드를 사용합니다. RESULT_OK로 액티비티가 정상적으로 끝났음을 전달하게 됩니다. RESULT_OK를 반환하지 않고 중간에 비정상적으로 종료되었다면 저 코드를 반환받지 못하므로 뭔가 문제가 있구나 알게 되겠죠? 제데로 종료가 된다면, 아까 우리가 추가로 입력한 데이터를 담은 인텐트도 함께 반환하게 됩니다.

이렇게.. 여기까지 정상적으로 돌아간 후, 호출당한 액티비티(InformationProc)가 finish()메소드에 의해 종료되게 되면, OnActivityResult() 메소드가 호출되게 됩니다. 결과를 기다리고 액티비티를 호출했으니, 액티비티가 종료되었으니 그 결과를 확인해야겠죠??


void onActivityResult(int requestCode, int resultCode, Intent data)
startActivityForResult로 호출한 액티비티가 종료되었을 때 호출됩니다.



01.protected void onActivityResult(int requestCode, int resultCode, Intent data)
02.{ super.onActivityResult(requestCode, resultCode, data);
03. TextView name_view = (TextView)findViewById(R.id.name_view);
04. TextView digit_view = (TextView)findViewById(R.id.digit_view);
05. if(resultCode==RESULT_OK) // 액티비티가 정상적으로 종료되었을 경우
06. {
07. if(requestCode==1) // InformationInput에서 호출한 경우에만 처리합니다.
08. {
09. // 받아온 이름과 전화번호를 InformationInput 액티비티에 표시합니다.
10. name_view.setText(data.getStringExtra("data_name"));
11. digit_view.setText(data.getStringExtra("data_digit"));
12. }
13. }
14. }


위의 onActivityResult에서, requestCode가 아까 setResult()에서 액티비티가 정상 종료되었는지를 판단하는 인자값, RESULT_OK를 받게 됩니다. 그래서, 이걸 가지고 적절히 예외 처리를 해 줄 수 있는 거죠.
requestCode는 아까 startActivityForResult()를 호출할 때, InformationInput이 호출한 것임을 표시하기 위해 '1'으로 설정하였으므로, 여기에서 또한 그 코드를 맞춰주어야 제데로 결과값을 받을 수 있습니다.

즉, 정상적으로 액티비티가 종료되었다면 requestCode의 값은 RESULT_OK, resultCode는 1이 됩니다.

이렇게 해서, 모두 정상이라면 인텐트에서 받아온 데이터를 꺼내 화면에 표시합니다.

putExtra() 메소드가 어떤 타입이든 상관없었던 것에 비해, 불러올 때에는 getStringExtra()메소드를 사용하여 문자열 값을 불러오면 됩니다. getStringExtra()뿐 아니라 getIntExtra(), getBooleanExtra() 등 여러 가지가 있으므로 상황에 맞추어 사용하면 됩니다.

이렇게 해서, 화면에 표시되는 TextView의 텍스트 값들이 아까 호출한 액티비티의 값들로 바뀌게 됩니다. :)


이렇게 해서, 인텐트를 통해 액티비티간에 데이터를 주고받는 것에 대해서 알아보았습니다. 이번 강좌는 다른 강좌들과는 다르게 세세한 부분에 대한 설명은 대부분 생략하였습니다. 이 강좌쯤을 보시는 분들은 어느 정도 기초가 되어 있으리라 믿기에, 일부러 안 적었습니다. 게다가 그걸 다 적으면 강좌가 한도끝도 없이 길어지기만 하죠 -_-

현재, 이 코드는 모든 문자열 값을 strings.xml에 넣어서 그 쪽에 있는 값들을 참조하는 형식으로 구성되어있습니다. 이 부분에 대해 궁금하신 분은 제가 2009/03/14 - [안드로이드/안드로이드 입문] - [강좌] 외부 리소스 사용하기 (문자열) 에 정리해놓았으니, 이걸 보시면 되겠습니다. :)

 

 

출처:http://androidhuman.tistory.com/125

Posted by 90002

[안드로이드]이미지 드래그해서 이동, 핀치투줌으로 확대축소하는 법(멀티터치)

멀티 터치 관련 글들을 많이 찾아봤으나, 

아무리 찾아봐도 제대로 구현해놓은 것이 없어서 직접 구현해보았습니다.

드래그를 이용한 이미지 이동, 핀치투줌을 이용해서 이미지를 확대, 축소 합니다. 

이후로는 회전도 가능하도록 할 예정입니다. 회전은 Matrix를 이용해야겠지요.


  1.MovingUnit.class

실제 움직일 unit을 컨트롤한다.

package beginners.ruler;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MovingUnit{
	//이미지
	private Bitmap Image;
	
	private float X;
	private float Y;

	private float Width;
	private float Height;
	
	//처음 이미지를 선택했을 때, 이미지의 X,Y 값과 클릭 지점 간의 거리
	private float offsetX;
	private float offsetY;
	
	// 드래그시 좌표 저장

	int posX1=0, posX2=0, posY1=0, posY2=0;	    

	// 핀치시 두좌표간의 거리 저장

	float oldDist = 1f;
	float newDist = 1f;
	
	// 드래그 모드인지 핀치줌 모드인지 구분
	static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;

	int mode = NONE;	
	


	//Image를 인자로 받는다.
	public MovingUnit(Bitmap Image) {
		// TODO Auto-generated constructor stub
		this.Image=Image;
		
		setSize(Image.getHeight(),Image.getWidth());
		setXY(0,0);
		
	}

	public void TouchProcess(MotionEvent event) { 
	    int act = event.getAction();
	     switch(act & MotionEvent.ACTION_MASK) {
	        case MotionEvent.ACTION_DOWN:    //첫번째 손가락 터치
	        	if(InObject(event.getX(), event.getY())){//손가락 터치 위치가 이미지 안에 있으면 DragMode가 시작된다.
		        	posX1 = (int) event.getX();
		            posY1 = (int) event.getY();
		            offsetX=posX1-X;
					offsetY=posY1-Y;
					
		            Log.d("zoom", "mode=DRAG" );
	
		            mode = DRAG;		            
	        	}
	            break;

	        case MotionEvent.ACTION_MOVE: 
	            if(mode == DRAG) {   // 드래그 중이면, 이미지의 X,Y값을 변환시키면서 위치 이동.
	            	X=posX2-offsetX;
		    		Y=posY2-offsetY;
	            	posX2 = (int) event.getX();
	                posY2 = (int) event.getY();
	                if(Math.abs(posX2-posX1)>20 || Math.abs(posY2-posY1)>20) {
	                    posX1 = posX2;
	                    posY1 = posY2;
	                    Log.d("drag","mode=DRAG");
	                }

	            } else if (mode == ZOOM) {    // 핀치줌 중이면, 이미지의 거리를 계산해서 확대를 한다.
	                newDist = spacing(event);
	               
	                if (newDist - oldDist > 20) {  // zoom in
	                	 float scale=FloatMath.sqrt(((newDist-oldDist)*(newDist-oldDist))/(Height*Height + Width * Width));
		                 Y=Y-(Height*scale/2);
		                 X=X-(Width*scale/2);
		                		 
		                 Height=Height*(1+scale);
		                 Width=Width*(1+scale);
		                
	                	 oldDist = newDist;
	                    
	                 } else if(oldDist - newDist > 20) {  // zoom out
	                	 float scale=FloatMath.sqrt(((newDist-oldDist)*(newDist-oldDist))/(Height*Height + Width * Width));
		                 scale=0-scale;
		                 Y=Y-(Height*scale/2);
		                 X=X-(Width*scale/2);
		                		 
		                 Height=Height*(1+scale);
		                 Width=Width*(1+scale);
		                
	                	 oldDist = newDist;
	                }
	            }
	            break;

	        case MotionEvent.ACTION_UP:    // 첫번째 손가락을 떼었을 경우
	        case MotionEvent.ACTION_POINTER_UP:  // 두번째 손가락을 떼었을 경우
	            mode = NONE;
	            break;
	        case MotionEvent.ACTION_POINTER_DOWN:  
	        //두번째 손가락 터치(손가락 2개를 인식하였기 때문에 핀치 줌으로 판별)
        		mode = ZOOM;
	            newDist = spacing(event);
	            oldDist = spacing(event);
	            Log.d("zoom", "newDist=" + newDist);
	            Log.d("zoom", "oldDist=" + oldDist);
	            Log.d("zoom", "mode=ZOOM");
        	
	            break;
	        case MotionEvent.ACTION_CANCEL:
	        default : 
	            break;
	    }

	}
	//Rect 형태로 넘겨준다.
	public Rect getRect(){
		Rect rect=new Rect();
		rect.set((int)X,(int)Y, (int)(X+Width), (int)(Y+Height));
		return rect;
	}

	 private float spacing(MotionEvent event) {
	    float x = event.getX(0) - event.getX(1);
	    float y = event.getY(0) - event.getY(1);
	    return FloatMath.sqrt(x * x + y * y);

	}
	 public boolean InObject(float eventX,float eventY){
		if(eventX<(X+Width+30) &&  eventX>X-30 && eventYY-30){
			return true;
		}
		return false;
	}	
	 public void setSize(float Height,float Width){
			this.Height=Height;
			this.Width=Width;
			
		}
	public void setXY(float X, float Y){
		this.X=X;
		this.Y=Y;
	}
	public Bitmap getImage(){
		return Image;
	}
}
2.MovingObject.class 
 실질적으로 main함수 역할을 한다.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.shapes.Shape;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class MoveObject extends View{
	int X,Y,Height,Width;
	private MovingUnit MU;
	
	public MoveObject(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	public void setSelectedImage(String ImagePath){
		Bitmap Image=BitmapFactory.decodeFile(ImagePath);
		MU=new MovingUnit(Image);
		invalidate();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		MU.TouchProcess(event);
		invalidate();
		return (true);
	}
	
	@Override
	
	public void draw(Canvas canvas) {
		// TODO Auto-generated method stub
		canvas.drawBitmap(MU.getImage(), null,  MU.getRect(), null);
		
		
		super.draw(canvas);
	}
}

결과 화면


모르는 것 있으시면 댓글로 남겨주세요:)




Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
Please check logcat output for more details.
Launch canceled!

안드로이드 컴파일을 시키면 위와 같은 에러 메시지 때문에 실행이 안되는 경우가 종종 있다.

이는 내장 메모리 공간이 부족하다는 메세지이다.

프로그래밍을 하다보면 Log가 쌓이는데, 그 작은 로그들이 쌓여서 내장 메모리의 공간을 많이 사용하게 된다.

그래서 log 데이터를 삭제해야한다.

 

-에뮬레이터에서 문제가 생길 시에는

1. log 데이터를 삭제(http://devbible.tistory.com/22 참조)

/>adb shell

# cd data
cd data
# cd log
cd log
# rm *
rm *


2. 에뮬레이터의 용량 크게 설정(http://kheru.tistory.com/53 참조)

- 콘솔을 사용하여 설정하기
emulator -partition-size 256 @AVD명

- 이클립스의 Run 실행에서 설정하기
Run > Run configuration > 해당 프로젝트 > Target >
Additional Emulator Command Line Options 에 아래 코드를 입력;
-partition-size 256

[출처]http://futureworker.tistory.com/9

 하면 되지만,

 

- 에뮬레이터가 아닌, 휴대폰에서 위와 같은 문제가 발생할 수 있다.

그럴 때는 adb shell을 통해서 해도 되지만 그렇게 하기 위해서는 permission을 accept 해야하는 번거로움이 있다.

다른 방법은 History Eraser라는 어플을 사용하는 방법이다.

History Eraser는 휴대폰 사용 기록을 없애주는 어플인데,

아래와 같이 [Clear All Apps Cache]를 삭제하면 로그기록까지 삭제해서 내장 메모리 공간을 확보할 수 있다.

Posted by 90002
//파일명 불러와서 저장할 파일명 정하기
     File files = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/ruler");
     int max=0;

     if(files.listFiles().length>0){  // 안에 있는 파일의 갯수가 0보다 클때  
      for(File list : files.listFiles()){
        String text=list.getName().substring(3,7);
        if(isNaN(text)){
         int num=Integer.parseInt(text);
         if(num>max){
          max=num;
         }
        }
        Log.e("1","name: "+ list.getName());  // 로그에 불러온 파일의 이름
       }
     }
     
     
     Bitmap bm = (Bitmap) data.getExtras().get("data");
     String filename = "CAM"+String.format("%5d", max)+".jpg";
     Log.e("2","file name: "+ filename);
     
           File f = new File(Environment.getExternalStorageDirectory()+"/ruler", filename);
           
           try {

            f.createNewFile();

            OutputStream outStream = new FileOutputStream(f);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            
            uri=Uri.fromFile(f);
            outStream.close();

        } catch (IOException e) {

            e.printStackTrace();

           }

Posted by 90002

치수

XML에서 씨는 치수에 대한 설명입니다. 치수는 측정의 단위라고 할 수 있겠지요. 예를 들면 10px, 2in, 5sp 등등. 아래의 측정 단위가 안드로이드에서 제공됩니다.

dp(==dip)
Density-Independent Pixels(밀도 독립 픽셀). 스크린의 물리적 밀도에 기반을 한 압축적인 단위입니다. 이 단위는 160 dpi(dots per inch) screen에 상대적입니다.
=>즉, 160dpi 스크린에서의 1px이 1dp라고 생각하시면 됩니다. 이름에서 밀도에 독립적이라고 밝힌 것과 같이, 스크린의 dpi가 다른 기계에서도 1dp의 실제 크기는 똑같다고 볼 수 있습니다.

sp
Scale-independent Pixels(배육 독립 픽셀). dp와 비슷합니다만, 사용자의 font size에 비례하게 됩니다. 이것은 font size의 크기로 쓰기를 추천합니다.
=>저는 다른 사이즈들은 대개 dp로 쓰고, 폰트 사이즈만 sp로 씁니다. 사용자가 지정해놓은 font size에 따라서 글자 크기가 변하나 봅니다.

pt
Points-스크린 사이즈의 1/72를 1pt라고 합니다.
=>스크린 사이즈에 비례해서 작업을 할 때 유용하다고 할 수 있습니다.

px
픽셀.

mm
밀리미터

in
인치

XML 작업할 때 항상 단위가 헷갈리더라구요.

특히나 지금 작업하고 있는 앱이 길이 측정 관련 앱이라서 정리가 필요하다고 생각했습니다.

좋은 정보 되시고, 굿 프로그래밍 되시길 바라요!



Dimension


A dimension value defined in XML. A dimension is specified with a number followed by a unit of measure. For example: 10px, 2in, 5sp. The following units of measure are supported by Android:

dp
Density-independent Pixels - An abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi (dots per inch) screen, on which 1dp is roughly equal to 1px. When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion. Using dp units (instead of px units) is a simple solution to making the view dimensions in your layout resize properly for different screen densities. In other words, it provides consistency for the real-world sizes of your UI elements across different devices.
sp
Scale-independent Pixels - This is like the dp unit, but it is also scaled by the user's font size preference. It is recommend you use this unit when specifying font sizes, so they will be adjusted for both the screen density and the user's preference.
pt
Points - 1/72 of an inch based on the physical size of the screen.
px
Pixels - Corresponds to actual pixels on the screen. This unit of measure is not recommended because the actual representation can vary across devices; each devices may have a different number of pixels per inch and may have more or fewer total pixels available on the screen.
mm
Millimeters - Based on the physical size of the screen.
in
Inches - Based on the physical size of the screen.

출처 : http://developer.android.com/guide/topics/resources/more-resources.html#Dimension

Posted by 90002
이전버튼 1 이전버튼

블로그 이미지
90002

공지사항

Yesterday1
Today3
Total125,057

최근에 달린 댓글

최근에 받은 트랙백

글 보관함