알고리즘 문제를 보면 해결할 방법이 여러가지인게 재밌는 부분인것 같다. 물론 방법이 여러가지라고 모두 좋은 방법만 있지는 않지만 생각하지 못했던 방법을 보고 공부가 되기도하고 생각하는 방법이 늘어나 재밌는 것 같다.

 

이번에 풀어볼 문제는 Leetcode라는 사이트에 있는 문제입니다.

 

344. ReverseString이란 문제이며 난이도는 easy 입니다.

코드는 아래의 링크를 통해 확인해볼 수 있습니다.

 

문제 : 문자열을 Reverse(뒤집는)하는 함수를 만들어라.


    조건 1. 입력 문자열을 char[] 형태로 제공된다.
    조건 2. 다른 Array에 추가 공간을 할당하지 않는다.
    조건 3. 모든 문자는 출력가능한 아스키 문자로 구성된다고 가정한다.

Example 1
    Input: ["h","e","l","l","o"]
    Output: ["o","l","l","e","h"]

Example 2
    Input: ["H","a","n","n","a","h"]
    Output: ["h","a","n","n","a","H"]

 


Solution 1. 반복문 활용하기
    Input 문자열의 크기만큼 반복문을 사용해 역순으로 출력하기

Solution 2. 반복문 활용하기
    Reverse는 뒤집는 것이므로 1 2 3 4 5 가 있을 때 5 4 3 2 1 이 되야 하는 것.
    1 2 3 4 5
    5 4 3 2 1
    이 형태를 보면
    1 5를 바꾸고
    2 4를 바꾸는 형태임을 확인할 수 있다.

    즉, Swap하면 n번의 반복문이 절반으로 줄어들 수 있게 된다.

Solution 3. 제공되는 함수 활용하기

 

주의사항
    main에 있는 원본 Input에 변화가 생길 수 있다.

    1번은 역순으로 출력을 하여 원본에 변화가 생기지 않지만,
    2번과, 3번은 원본에 변화가 생기게 되므로 주의해야한다.

    만약 원본이 변하지 않길 바란다면 s를 그대로 넘겨주지 말고
    s.copyOf(), s.clone() 를 이용하면 된다.

copyOf(), clone() 디버깅

    위의 이미지는 디버깅을 했을 때 나타나는 값들이다.

    s는 원본 데이터

    copyOfs는 s.copyOf()의 결과

    cloneS는 s.clone()의 결과

    이미지를 보면 알 수 있듯이 각각 다른 객체임을 확인할 수 있다.

 

    그럼 정말로 객체를 함수에 넘겨주었을 때 같은 객체가 넘어가는지 아래의 이미지를 통해 확인해보겠습니다.

    먼저 main의 s객체를 보면 @818임을 확인할 수 있다.

main에서의 s객체

   main에서 reverseString1() 함수의 파라미터로 넘겨주고 함수에서 s객체를 확인해보면 아래와 같다.

reverseString1(s)의 s객체

    main의 객체와 같은 객체임을 확인할 수 있다. 따라서 함수에서 객체의 변화를 주면 함수안에서만 변화가

    일어나는 것이 아니라 밖에서도 변화가 유지될 수 있으므로 주의하는게 좋다.

 

 

copyOf()로 얻은 객체와, clone()으로 얻은 객체가 다른 객체임을 확인해봤는데 이들을 비교하면 어떤 결과가 나오게될지 궁금해져 비교를 해보게 되었다.

s == s.copyOf()
s == s.clone()

s.equals(s.copyOf())
s.equals(s.clone())

위의 결과가 어떻게 나오게 될까?

 

결과

더보기
s == s.copyOf() // false
s == s.clone() // false

s.equals(s.copyOf()) // false
s.equals(s.clone()) // false

 생각했던대로 결과가 나왔나요? 위의 코드는 같은 코드이기에 같은 결과를 얻게됩니다.

만약 객체의 내용물을 비교하고 싶다면 어떻게 해야 했을까요? contentEquals()라는 메서드를 사용하면 됩니다.

 

아래의 이미지를 통해 결과를 확인해볼 수 있습니다.

==, equals, contentEquals() 비교

 

 

Code

Reference

 

 

'Algorightm' 카테고리의 다른 글

[Kotlin] 387.First Unique Character in a String [LeetCode]  (0) 2020.05.12
[Level1] 완주하지 못한 선수  (0) 2019.10.24
Hash Algorithm  (0) 2019.10.14
시간복잡도를 알아보자  (0) 2019.07.17

안드로이드 프레임워크에서 제공되는 위젯들(TextView, EditText, Button 등)이나 레이아웃으로는 원하는 뷰를 만들기가 어려울 때가 있습니다. 그렇다고 포기하는 게 아니라 직접 뷰를 만들어 구현하는 건 어떨까요? 이번 글에서는 CustomView를 만드는 방법에 대해 알아보겠습니다.

 

CustomView를 만드는 기본적인 원리

  • 기존에 존재하는 View클래스를 상속합니다.
  • 시작하는 키워드가 'on'인 super 클래스 메서드를 오버라이드 합니다.
  • 새로 만든 커스텀 뷰를 사용합니다.

onDraw()

  • 개발자가 원하는 대로 구현할 수 있는 Canvas를 제공합니다. 
    • Canvas는 도화지라고 생각하면 이해가 조금 쉽습니다.
  • Canvas를 이용해 그리고 싶은 내용을 화면에 그리면 됩니다.

onMeasure()

  • 뷰와 뷰에 포함된 콘텐츠를 측정하여 측정된 Width와 Height을 결정합니다.
  • onMeasure()는 measure(int, int)에 의해 호출됩니다. 
    • measure() 메서드에서는 뷰의 사이즈를 측정하고 실제 측정된 사이즈가 수행되는 곳은 onMeasure()입니다.
  • onMeasure()를 오버라이드 하는 경우 setMeasuredDimension(int, int)를 호출해서 측정된 사이즈를 저장할 수 있도록 해야 합니다.

프레임워크가 호출하는 다른 View 메서드

생성

  • 생성자
    • 뷰가 런타임에 코드로부터 생성되는 경우
    • xml파일을 파싱하는 경우
  • onFinishInflate()
    • 뷰, 뷰그룹의 경우 자식 뷰들이 인플레이션이 다 끝나면 호출됩니다.

레이아웃

  • onMeasure(int, int)
    • 뷰, 자식뷰의 사이즈가 결정될 때 호출됩니다.
  • onLayout(boolean, int, int, int, int)
    • 뷰, 자식뷰의 위치가 결정될 때 호출됩니다.
  • onSizeChanged(int, int, int, int)
    • 뷰의 사이즈가 변경되었을 때 호출됩니다.

그리기

  • onDraw(Canvas)
    • 뷰가 가지고 있는 컨텐츠를 그릴 때 호출됩니다.

이벤트 처리

  • onKeyDown(int, KeyEvent)
    • 키 이벤트가 눌렸을 때 호출됩니다.
  • onKeyUp(int, KeyEvent)
    • 키가 눌린 게 떨어졌을 때 호출됩니다.
  • onTrackballEvent(MotionEvent)
    • 트랙볼 이벤트 발생 시 호출됩니다.
  • onTouchEvent(MotionEvent)
    • 터치 이벤트 발생 시 호출됩니다

포커스

  • onFocusChanged(boolean)
    • 포커스를 잃을 때 호출됩니다.
  • onWindowFocusChanged(boolean)
    • 윈도우가 포함하고 있는 뷰가 포커스를 얻거나 잃을 때 호출됩니다.

Attaching

  • onAttachedToWindow()
    • 윈도우에 뷰가 붙을 때 호출됩니다.
  • onDetachedFromWindow()
    • 윈도우로부터 뷰가 떨어질 때 호출됩니다.
  • onWindowVisibilityChanged(int)
    • 윈도우가 가지고 있는 뷰의 가시성이 변경될 때 호출됩니다.

Custom View에 대해서 조금 알아봤는데요. 그럼 직접 Cutstom View를 만들어 보겠습니다.

 

이번에 만들 Custom View는 LinedEditText입니다. LiendEditText는 밑줄이 있는 EditText입니다.

 

LinedEditText

 

위의 사진처럼 EditText에 각 줄마다 밑줄이 생기는 EditText입니다.

 

LinedEditText는 EditText를 상속하는 클래스를 만들면 되는 간단한 Custom View입니다.

 

추가적으로 작업한 것은 EditText의 크기에 비해 Cursor의 크기가 너무 커서 Cursor의 크기를 줄이기 위한 Drawable을 만들었습니다. EditText의 android:textCursorDrawable에 만든 Drawable을 적용해 Cursor를 수정할 수 있습니다.

 

EditText의 Default로 보여지는 밑줄은 android:background의 속성을 수정하여 없앨 수 있습니다.

 

Code

Reference

EditText에 입력을 할 때 핸드폰의 키패드가 올라오게 됩니다. 이 때, 뷰의 하단에 있는 UI가 키패드가 올라옴에 따라 어떻게 보이길 원하나요? 보이는게 좋은가요? 아니면 가려지길 바라나요? 이번 글에선 이부분을 다뤄보겠습니다.

 

먼저 아래와 같은 뷰가 있습니다.

 

 

 

이 때 EditText에 입력을 하는데 RecyclerView가 키패드와 같이 따라 올라와 뷰가 이상해집니다.

이 문제는 어렵지 않게 해결할 수 있습니다. 

 

AndroidManifest.xml 파일에서는 키패드가 나타날 때 UI를 어떻게 처리할지 정할 수 있습니다.

 

AndroidManifest.xml 파일로 이동하여 해당 액티비티에 아래와 같은 속성을 적용해줍니다.

android:windowSoftInputMode="adjustPan"

이 속성은 키패드가 올라올 때 UI를 덮도록 설정해 줍니다.

android:windowSoftInputMode="adjustNothing"

이 속성도 UI와 관계없이 키패드가 올라오도록 해줍니다.

 

 

만약 UI가 잘리지 않고 그대로 보여지고 싶다면 아래와 같이 속성을 적용해주면 됩니다.

android:windowSoftInputMode="adjustResize"

 

'Android' 카테고리의 다른 글

@JvmOverloads  (0) 2020.12.15
@JvmOverloads  (0) 2020.12.15
[Android] 테스트  (0) 2020.04.11
[Android] Gradle  (0) 2020.04.10
[Android] ContentProvider, Service, BroadcastReceiver  (0) 2020.04.03

+ Recent posts