[Android] Dialog 크기 변경하기

안드로이드를 탑제하는 디바이스 제조사는.. 안드로이드 운영체제의 외형(Theme)을 원하는대로 커스터마이징할 수 있습니다. 내부 핵심 코어는 동일하나.. 외형을 다르게 함으로써 안드로이드는 다양한 모습으로 사용자에게 전달됩니다.. 이러한 안드로이드의 특징은 분명 장점입니다만.. 제조사와 개발자에게 이러한 다양성은 골치 아픈 “선택”입니다..

갤럭시 노트에 맞도록 UI를 구성한 앱을 그대로 갤럭시탭 10.1에서 실행해보니.. UI가 싸그리 깨져버려.. 다시 갤럭시탭 10.1에 맞도록 UI를 재구성하게 되었는데요. 갤럭시 노트의 해상도와 탭 10.1의 해상도는 동일하나.. DPI가 다르므로 나타나는 것으로.. 만약 해상도가 달라졌다면 더욱 골치 아팠겠지요..

여튼…. UI를 맞추는 도중.. Dialog의 크기를 조정해야할 필요가 있었습니다.. 갤럭시 노트에서는 별 문제가 없었으나.. 탭에서는 폰트가 커지는 바램에 아래의 화면처럼 컨텐츠가 Dialog 크기보다 넘치는 문제가 발생했습니다..

사용자 삽입 이미지
뭐… Dialog의 너비를 늘리면 해결될일.. 해서 다음과 같은 코드로 Dialog의 크기를 확장했습니다.

AlertDialog.Builder adb = new AlertDialog.Builder(context);
adb.setTitle("경사도 측정 결과");
adb.setPositiveButton("확 인", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {}
});
      
adb.setView(pieChartView);
      
Dialog dialog = adb.create();
      
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = 800;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
      
dialog.show();
Window window = dialog.getWindow();
window.setAttributes(lp);

일반적으로 대화창을 화면에 표시하는 코드에 대해서 대화창의 크기를 늘려주는 코드로 추가된 것은 11번 ~ 14번 그리고 17번 ~ 18번 코드입니다. 13번 코드에서 800 픽셀 크기로 늘렸습니다. 그리고 실행해보니 원하는대로 크기가 늘어났습니다.

사용자 삽입 이미지
근데… 가만히 보면.. 이상한게 있습니다.. 대화창의 가장자리의 반투명 효과가 제대로 먹히질 않습니다. 이는 기본적으로 탭10.0에서 제공하는 테마(Theme)에서 대화상자의 크기는 딱! 정해져 있습니다. 즉, 크기 자체도 테마 값으로 생각할 수 있습니다. 대화상자의 크기를 키우면? 기존의 테마값들 중 몇가지가 초기화되는 모양입니다. 초기화된 녀석이 무엇인지 찾아보면 해결할 수 있겠지요..

대화상자의 크기값을 지정함으로써 초기화된 속성은 대화상자의 배경으로 사용될 Drawable 객체입니다. 이 녀석이 기본값인 검정색 Drawable로 초기화된 것으로 예상되고….. 그렇다면 이 녀석을 완전 투명으로 처리한다면 해결될듯합니다.. 이에 대한 코드를 앞서 언급한 코드에 덧붙이면 다음과 같습니다.

AlertDialog.Builder adb = new AlertDialog.Builder(context);
adb.setTitle("경사도 측정 결과");
adb.setPositiveButton("확 인", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {}
});
      
adb.setView(pieChartView);
      
Dialog dialog = adb.create();
      
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = 800;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
      
dialog.show();
Window window = dialog.getWindow();
window.setAttributes(lp);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

새롭게 추가된 코드는 오직 19번 코드입니다. 함수명 자체가 앞서 설명드린 것을 그대로 나타내고 있습니다. 실행해보면… 아래의 화면처럼 완벽하게 원하는 결과를 얻을 수 있습니다.

사용자 삽입 이미지

[Android] 이미지 회전 또는 Mirror(반전)

작디 작은 화면을 가지는 모바일 디바이스.. 요즘은 작다고 하면 한대 맞은 시대이긴 하지만 말입니다. 여튼 모바일 디바이스에서 이미지를 참 많이 가져다 사용합니다. 아래의 코드는 파일명으로 해서 코드단에서 쉽게 사용할 수 있는 Bitmap을 하나 만드는 코드입니다.

BitmapFactory.Options bo = new BitmapFactory.Options();
bo.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeFile(imageFilename, bo);

...

bmp.recycle(); 

와우..  참 쉽죠?  사실 1번과 2번 코드는 옵션입니다. 이 코드가 필요없을때는 BitmapFactory의 decodeFile 함수의 두번째 인자를 null로 주면 됩니다. 생성한 비트맵을 잘썼다면 7번 코드를 호출해 줍니다.

이 글의 요지는 이렇게 비트맵을 생성하는게 아니고.. 생성된 비트맵을 회전하고 Mirror시키는 방법이니다. 먼저 회전입니다.

Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap newBmp = Bitmap.createBitmap(bmp, 0, 0, 
    bmp.getWidth(), bmp.getHeight(), matrix, true); 

2번 코드에서 postRotate 함수의 첫번째 인자가 바로 회전하고자 하는 각도입니다. 다음은 Mirror 시키는 코드입니다.

float[] mirrorY = {
    -1, 0, 0,
    0, 1, 0,
    0, 0, 1
};

Matrix matrix = new Matrix();
matrix.setValues(mirrorY);
Bitmap newBmp = Bitmap.createBitmap(bmp, 0, 0,
     bmp.getWidth(), bmp.getHeight(), matrix, true); 

회전처럼 행렬을 이동하기는 하는데.. Mirror의 경우 직접 행렬요소를 직접 지정하고 있습니다. 행렬(Matrix)는 개발자에게 매우 유용한 수학적 도구중에 하나가 분명합니다.

안드로이드에서 비트맵에 대한 이야기가 나온 차에 하나 더…! 비트맵을 파일로 저장하는 방법입니다. 안드로이드는 PNG와 JPG 포맷을 지원합니다. 아래의 코드는 비트맵을 PNG 포맷에 대한 파일로 저장하는 코드입니다.

File file = new File(filename);
FileOutputStream filestream = null;
try {
    filestream = new FileOutputStream(file);
    newBmp.compress(CompressFormat.PNG, 0, filestream);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

[Android] 모바일 디바이스에 저장된 전체 이미지 파일 가져오기

안드로이드를 처음 학습할때… 첨으로 별나다.. 싶었던 기억이 이었습니다만.. 지금은 제법 잘만들어진 프레임워크라는 생각이 듭니다. 버전업이 많이 되어져.. 안정화가 되었다는 것이 가장 큰 이유인듯 하지만 말입니다. 아래의 코드는 디바이스에 저장된 이미지 파일(PNG, JPG)들 전체를 얻는 코드입니다.

String[] proj = { MediaStore.Images.Media.DATA };
Cursor imageCursor = managedQuery(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj, null, null, null);
   
if (imageCursor != null && imageCursor.moveToFirst()){
    String fileName;
    int dataCol = imageCursor.getColumnIndex(MediaStore.Images.Media.DATA);
    
    do {
        fileName = imageCursor.getString(dataCol);
        if (fileName != null){
            // fileName(이미지 파일명)
        }
    } while (imageCursor.moveToNext());

    imageCursor.close();
}

[Android] GPS 기능 관련 API 예제

모바일이 이미 충분히 대중화되었음으로 해서.. GIS 분야 중 하나인 LBS(Location Based System; 위치 기반 시스템)을 활용할 수 다양한 앱이 꽃을 피울 기회를 맞이 한지 이미 꽤 오래되었습니다.

이에 안드로이드가 탑재된 모바일 기기의 GPS를 통해 현재 자신의 위치를 얻을 수 있는 안드로이드 API를 활용하는 샘플 코드를 공유해 봅니다. 아래는 샘플 코드에 대한 스크린 샷입니다.

사용자 삽입 이미지
위치(WGS84 타원체에 대한 경위도)는 물론이고 현재 이동 속도과 위치 정확도(휴대용 GPS의 경우 최고의 정확도 오차는 10m로 제한됨) 등을 얻어와 화면에 표시하고 있습니다. 또한 GPS의 원체 데이터 형식인 NMEA0183을 표시하고 있습니다.

GPS에게 위치데이터 힌트를 제공하는 인공위성의 수 역시 제공하고 있는데요. 이 인공위성의 수는 NMEA0183 데이터로부터 얻어올 수 있습니다. 긴 설명보다는 실제 실행 가능한 예제 코드 샘플을 공유합니다.

인터넷 상에서 공유되고 있는 다양한 소스를 취합하여 이 하나의 예제 샘플을 제작했습니다. 안드로이드에서 GPS로부터 위치 데이터 등을 취득하고자 하시는 개발자 분들에게 조금이라도 도움이 되시길 바랍니다.

GPS로부터 수신받은 좌표(WGS84 타원체의 경위도 좌표)를 다른 좌표계로 변환하기 위한 방법은 다음 URL을 통해 살펴보시기 바랍니다.

[Android] OpenGL ES에서 텍스쳐맵핑용 비트맵 생성

몇일전.. 안드로이드에서 OpenGL ES의 텍스쳐 맵핑을 살펴보고 실습을 해보면서.. 아무리 해도 텍스쳐가 맵핑되지 않았습니다.. 일단 OpenGL에서 텍스쳐맵핑을 위한 OpenGL의 API의 사용순서에 문제가 있겠거니.. 하며 문제를 파악해 나갔지만.. 도통 모르겠다 싶었구요.. 그러던중.. 문제를 해결.. ㅜㅜ

텍스쳐 맵핑을 하기위한 준비 과정으로 먼저 Bitmap 객체를 하나 생성해야 하는데.. 아래의 코드를 통해 Bitmap 객체를 생성했었습니다.

Bitmap bitmap = 
    BitmapFactory.decodeResource(context.getResources(), R.drawable.texture);

이 한줄로 비트맵을 포맷에 상관없이 읽을 수 있는 안드로이드의 API에 감탄을 했던것같은데.. 바로 문제는 여기에 있었습니다.. 이 코드를 아래 코드로 변경해야 텍스쳐가 맵핑됩니다.

Bitmap bitmap = null;
InputStream is = context.getResources().openRawResource(R.drawable.texture);
try {
    bitmap = BitmapFactory.decodeStream(is);
} finally {
    try {
        is.close();
        is = null;
    } catch(IOException e) {
        //.
    }
}

감탄했던 단 한줄의 코드 대신.. 원시 데이터로써 비트맵을 읽어 스트림을 만들고 이 스트림을 통해 비트맵을 만드는 제법 복잡다단한 방법이 바로 옳바른 방법이였습니다.. 아래는 그토록 보고 싶어라 했던 텍스쳐가 맵핑된 화면 결과…

사용자 삽입 이미지
흠…. 답답했던 때가 언제었냐는듯.. 눈이 맑아집니다.. ㅎㅎ 만약 첫번째 방식으로 하여 텍스쳐맵핑이 않되시는 분이 계시다면 두번째 방법으로 접근해 보시기 바랍니다.