블로그 이미지
매몰

모바일 어플리케이션 개발 1인 기업 고영진모바일입니다. 저와 함께 맛깔스러운 앱을 만들어 보아요~

Rss feed Tistory
개발/ios 2017.05.30 16:08

UIButton 이미지를 손쉽게 정렬하자~

아이폰 Swift에서 UIButton 안의 이미지를 원하는 위치에 두려면 

Edge Inset을 이용하여 좌우상하에 여백을 줘야 한다


여간 귀찮고 불편한 일이 아닐 수 없다


그래서 좀 더 편하게 이미지를 옮기는 방법을 소개한다


원리는 무지 간단하다

Edge Inset를 가로,세로 기준으로 이미지 크기와 함께 각각 계산해 주면 된다


왼쪽 정렬 

(L: 왼쪽 여백, R: 오른쪽 여백, M: 여백, IW: 이미지 너비, BW: 버튼 너비)





가운데 정렬 





이 두가지 경우만 이용하면 나머지 정렬도 모두 가능하다


코딩하면 다음과 같다

 


class ImageButton: UIButton {

    

    //가로 정렬 기준 (-1: 왼쪽, 0: 가운데, 1: 오른쪽)

    @IBInspectable var horizontal: Int = 0

    

    //세로 정렬 기준 (-1: , 0: 가운데, 1: 아래)

    @IBInspectable var vertical: Int = 0

    

    //기준으로부터의 거리 (여백)

    @IBInspectable var point: CGPoint = CGPointMake(0, 0)

    

    //이미지 크기

    @IBInspectable var size: CGSize = CGSizeMake(0, 0)

    

    private var mSetSize: CGSize?

    

    override func drawRect(rect: CGRect) {

        let width = frame.width

        let height = frame.height

        

        //처음 또는 버튼 크기가 달라지면 다시 위치 계산

        if  mSetSize == nil || !(mSetSize?.width == width && mSetSize?.height == height) {

            locate()

            

            //버튼 크기값 저장

            mSetSize = CGSizeMake(width, height)

        }

    }

    

    //위치 계산후 적용

    private func locate() {

        //가로 정렬

        let width = size.width

        let x1 = point.x

        let x2 = frame.width - x1 - width

        switch (horizontal) {

        case -1: //왼쪽 정렬

            

            //이미지 왼쪽은 여백 그대로

            imageEdgeInsets.left = x1

            

            //이미지 오른쪽은 버튼 너비에서 margin, 이미지 너비를 뺀다

            imageEdgeInsets.right = x2

            

        case 1: //오른쪽 정렬


            //왼쪽 정렬과 반대로 한다

            //이미지 왼쪽은 버튼 너비에서 margin, 이미지 너비를 뺀다

            imageEdgeInsets.left = x2

            

            //이미지 오른쪽은 여백 그대로

            imageEdgeInsets.right = x1

            

        default: //가운데 정렬

            

            //이미지 왼쪽은 버튼의 가운데에서 여백 더하고 다시 이미지 너비의 절반을 뺀다

            imageEdgeInsets.left = ((frame.width / 2) + x1) - (width / 2)

            

            //이미지 오른쪽은 버튼 너비에서 위에서 계산한 왼쪽 좌표와 이미지 너비를 뺀다

            imageEdgeInsets.right = frame.width - (imageEdgeInsets.left + width)

        }

        

        //세로 정렬 (가로 정렬과 같은 원리로)

        let height = size.height

        let y1 = point.y

        let y2 = frame.height - y1 - height

        switch (vertical) {

        case -1: // 정렬

            

            imageEdgeInsets.top = y1

            imageEdgeInsets.bottom = y2

            

        case 1: //아랫 정렬

            

            imageEdgeInsets.top = y2

            imageEdgeInsets.bottom = y1

            

        default: //가운데 정렬

            

            imageEdgeInsets.top = ((frame.height / 2) + y1) - (height / 2)

            imageEdgeInsets.bottom = frame.height - (imageEdgeInsets.top + height)

        }

    }

}





스토리 보드로 적용해 보자






Custom Class를 위에서 만든 Image Button으로 바꾸고

다음과 같이 입력해 보자







실행하면 이런 모습이다 

버튼안의 이미지가 50x50 이고

가로는 왼쪽에서 20포인트, 세로는 가운데에서 10포인트 움직였다






 

 



수제 앱 장인: 고영진


고영진모바일 1인기업 대표 겸 개발자 

  

     실패만 하고 있어도 꿈을 포기하지 않는 남자 

     제가 직접 경험하고 습득한 지식을 위주로 올릴게요

 



사업자 정보 표시
고영진모바일 | 고영진 | 서울특별시 관악구 낙성대동 서울대연구공원 SK상생혁신센터 | 사업자 등록번호 : 109-11-82076 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2010-서울강서-0217호 | 사이버몰의 이용약관 바로가기
개발/android 2016.03.28 10:19

버튼의 Selector 이미지를 간절히 가져오고 싶다면?



보통 Selector를 xml로 아래와 같이 만들어 놓는다.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@drawable/btn" />
<item android:state_pressed="true" android:drawable="@drawable/btn_press" />
</selector>



그리고 버튼 background에 적용한다.

<Button android:id="@+id/Button" android:text="@string/btn"
android:layout_width="100dp" android:layout_height="100p"

android:background="@drawable/btn_selector"/>




별로~ 그럴일은 없지만 만약 이 selector의 android:drawable 이미지를 자바 코드상으로 불려오고 싶다면??


private Drawable[] getPressImages(View v) {
//Selector 이미지를 StateListDrawable 객체로 불러옴
StateListDrawable statedrawable = (StateListDrawable)v.getBackground();
if(statedrawable != null) {
try {
//Veiw의 현재 이미지 상태를 배열에 가져옴
int[] currentstate = v.getDrawableState();

//이미지를 불러오기 위해 인덱스와 이미지 메소드를 가져옴
Method indexmethod = StateListDrawable.class.getMethod("getStateDrawableIndex", int[].class);
Method drawblemethod = StateListDrawable.class.getMethod("getStateDrawable", int.class);

//인덱스 메소드와 상태 배열을 이용해 StateListDrawable의 리스트 인덱스를 가져옴
int index = (int) indexmethod.invoke(statedrawable, currentstate);

//얻어낸 리스트 인덱스로 StateListDrawable에서 이미지를 각각 불러옴
Drawable drawable1 = (Drawable) drawblemethod.invoke(statedrawable, index);
Drawable drawable2 = (Drawable) drawblemethod.invoke(statedrawable, index + 1);

return new Drawable[] {drawable1, drawable2};

} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

return null;
}


 

 



수제 앱 장인: 고영진


고영진모바일 1인기업 대표 겸 개발자 

  

     실패만 하고 있어도 꿈을 포기하지 않는 남자 

     제가 직접 경험하고 습득한 지식을 위주로 올릴게요

 




사업자 정보 표시
고영진모바일 | 고영진 | 서울특별시 관악구 낙성대동 서울대연구공원 SK상생혁신센터 | 사업자 등록번호 : 109-11-82076 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2010-서울강서-0217호 | 사이버몰의 이용약관 바로가기
개발/android 2015.04.19 00:30

버튼 누름 효과를 만드는 2가지 방법





버튼이면 당연히 있어야할 누름효과!

눌렸을때와 누르지않았을때가 같다면 과연 버튼일까?


당연하지만 그래서 잃혀지기 쉬운 기능

버튼의 누름효과!!


안드로이드에서 기본적인 버튼은 누름효과가 있다.

하지만 나만의 예쁜 버튼을 만들려고 이미지를 넣으면 이런 효과는 사라진다.


이때 누름효과가 생기도록 하는 2가지 방법이 있다.




첫번째는 xml의 selector를 이용하는 것이다.


res의 drawable 폴더에 button_selector.xml 파일을 만든다.

여기서 버튼의 일반이미지, 누름이미지를 다음과 같이 설정한다.


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

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

    <item android:state_pressed="false" android:drawable="@drawable/button" />

    <item android:state_pressed="true" android:drawable="@drawable/button_press" />

</selector>



그리고 layout의 버튼에 selector를 적용한다.


<Button android:id="@+id/Button"

android:layout_width="61dp" android:layout_height="35dp" 

android:background="@drawable/button_selector"></Button>




두번째는 자바코드로 넣는 것이다.


Button button = (Button)findViewById(R.id.Button);

button.setOnTouchListener(new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

switch(event.getAction()) {

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

v.setBackgroundResource(R.drawable.button);

break;

case MotionEvent.ACTION_DOWN:

v.setBackgroundResource(R.drawable.button_press);

}

return false;

}

});





 

 



수제 앱 장인: 고영진


고영진모바일 1인기업 대표 겸 개발자 

  

     실패만 하고 있어도 꿈을 포기하지 않는 남자 

     제가 직접 경험하고 습득한 지식을 위주로 올릴게요

 





사업자 정보 표시
고영진모바일 | 고영진 | 서울특별시 관악구 낙성대동 서울대연구공원 SK상생혁신센터 | 사업자 등록번호 : 109-11-82076 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2010-서울강서-0217호 | 사이버몰의 이용약관 바로가기
  • 혼마 2015.08.06 13:42 신고 ADDR 수정/삭제 답글

    이 두가지 방법에 차이점이 무엇인지 알려주실수 있나요?

    • 대세를 따르지 않고 대세를 만드는 매몰 2015.08.22 11:19 신고 수정/삭제

      xml의 selector 방식은 기본적으로 두장의 이미지로만
      보통과 누름을 표현해요

      하지만 자바코드 방식은 두장의 이미지로 뿐만 아니라
      한장의 이미지로 크기를 바꾸거나 투명도를 바꾸거나 하는식으로
      이미지리소스를 줄일 수 있고 또 무한한 응용이 가능해요

      즉, 간단한 기본적인 버튼을 만들시에는 xml로,
      더 확장된 버튼을 만들고자 할때는 자바코드가 좋죠

개발/android 2014.10.19 22:16

Surface View에서 간단한 이미지버튼 손수 만들기

앱을 제작할때에는 버튼 클래스가 기본적으로 제공된다..

하지만 SurfaceView 기반의 게임을 만들때는 그렇지 않기 때문에 손수 만들어야 한다..


빠른 이해를 위해 모든 군더더기는 다 빼고 이미지로만 이루어진 버튼 클래스를 만들어 보겠다..




클래스


public class GraphicButton {

public static final int IMAGE_UP = 0;

public static final int IMAGE_DOWN = 1;


private Bitmap[] mImage;

private Rect mRect;

public int mImageNum;

public GraphicButton(Rect rect) {

mRect = rect;

mImage = new Bitmap[2];

mImageNum = IMAGE_UP;

}

public void setImages(Bitmap upimage, Bitmap downimage) {

//이미지를 눌린 상태 및 아닌 상태 두가지로 저장한다 

mImage[IMAGE_UP] = upimage;

mImage[IMAGE_DOWN] = downimage;

}

public boolean touch(int tx, int ty) {

//이미지 좌표와 터치 좌표를 비교한다

Rect rect = mRect;

if((rect.left < tx && rect.right > tx) && (rect.top < ty && rect.bottom > ty))

return true;


return false;

}


public void setPress(boolean press) {

//버튼의 이미지를 변경하여 눌린 상태 및 아닌 상태를 표시한다

mImageNum = press ? IMAGE_DOWN : IMAGE_UP;

}


public void draw(Canvas canvas) {

//이미지 번호대로 이미지를 출력한다

int imagenum = mImageNum;

if(mImage[imagenum] != null)

canvas.drawBitmap(mImage[imagenum], null, mRect, null);

}


}  





사용법


private GraphicButton mButton;

private GameThread mThread;


public GameView(Context context, AttributeSet attrs) {

super(context, attrs);


SurfaceHolder holder = getHolder();

holder.addCallback(this);


//버튼을 원하는 위치에 생성

mButton = new GraphicButton(new Rect(100, 100, 300, 200));


//버튼 이미지 설정

Bitmap upimage = BitmapFactory.decodeResource(context.getResources(), R.drawable.upbutton);

Bitmap downimage = BitmapFactory.decodeResource(context.getResources(), R.drawable.downbutton);

mButton.setImages(upimage, downimage);


mThread = new GameThread(holder);

}


class GameThread extends Thread {

private SurfaceHolder mSurfaceholder;


public GameThread(SurfaceHolder surfaceHolder) {

mSurfaceholder = surfaceHolder;

}


@Override

public void run() {

SurfaceHolder surfaceHolder = mSurfaceholder;

Canvas c = null;


while(true) {

//게임 로직

//...


try{

c = surfaceHolder.lockCanvas(null);

synchronized(surfaceHolder) {

if(c != null)

doDraw(c);

}

sleep(mDelay);


}catch(InterruptedException e) {

e.printStackTrace();

}

finally {

if(c != null)

surfaceHolder.unlockCanvasAndPost(c);

}

}

}

}



private boolean doDraw(Canvas canvas) {

//배경 및 오브젝트 출력

//...


//버튼 출력

mButton.draw(canvas);

}


@Override

public boolean onTouchEvent(MotionEvent event) {

int touchx = (int)event.getX();

int touchy = (int)event.getY();

switch(event.getAction()) {

case MotionEvent.ACTION_CANCEL:

mButton.setPress(false);    //버튼 상태 초기화

break;


case MotionEvent.ACTION_UP:

mButton.setPress(false);    //버튼 상태 초기화

if(mButton.touch(touchx, touchy)) {

//버튼 클릭 행동

//...

}

break;


case MotionEvent.ACTION_MOVE:

//버튼 상태 변경

mButton.setPress(mButton.touch(touchx, touchy));

break;


case MotionEvent.ACTION_DOWN:

//버튼 상태 변경

mButton.setPress(mButton.touch(touchx, touchy));

} 

} 






게임에서는 버튼이 움직이는 등의 애니메이션이 많이 들어 간다.

그러기 위해서는 클래스를 확장하여 좀 더 알맞게 고쳐야 할 것이다.



 

 



수제 앱 장인: 고영진


고영진모바일 1인기업 대표 겸 개발자 

  

     실패만 하고 있어도 꿈을 포기하지 않는 남자 

     제가 직접 경험하고 습득한 지식을 위주로 올릴게요

 




사업자 정보 표시
고영진모바일 | 고영진 | 서울특별시 관악구 낙성대동 서울대연구공원 SK상생혁신센터 | 사업자 등록번호 : 109-11-82076 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2010-서울강서-0217호 | 사이버몰의 이용약관 바로가기
TOTAL 69,579 TODAY 8