최신 글
-
안드로이드
Kotlin DSL을 이해해보자 - 1. 확장함수타입
TL; DR DSL을 만들 때 인자로 넣는 Person.() -> Unit 은 확장함수타입이다. 확장함수를 인자로 넘겨주기 때문에 간략한 코드를 만들 수 있다. Kotlin DSL을 간단하게 말하자면 gradle의 dependencies를 보면 된다 dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version") implementation("org.koin:koin-android:1.0.2") . . . } 이렇게 dependencies의 블록 안에 실행하고자 하는 코드를 한줄 한줄 '선언'처럼 적어두게 하여 '명령형'이 아닌 '선언형'으로 코딩하게 하는 것이다. (Kotlin in action, pg.479)..
-
안드로이드
헤더가 찰싹 달라 붙는 스크롤 뷰 (Sticky Scroll View)
Fixed view in scroll view 네이버 앱을 보면 이렇게, 검색창이 위로 올라가다가 맨 위에 도달하면 더이상 올라가지 않고 고정이 된다. 실제로 네이버 앱 내부적으로는 CollapsingToolbarLayout을 이용하고 있을 수도 있다. 하지만, 만약 단순히 뷰를 고정시키기만 하고싶거나, 툴바는 다른 이유로 따로 쓰고 싶을 경우에는 CollapsingToolbarLayout를 사용하지 못한다. 그래서 이번에는 스크롤 뷰 내부의 임의의 뷰를 천장에 찰싹 달라 붙게 하는 커스텀 뷰를 만들어 보기로 하자. 전체 코드는 https://github.com/5seunghoon/Sticky_Scroll_View_Example 에 있고, 이번에는 https://github.com/amarjain07/S..
-
안드로이드
Android DiffUtil
리사이클러뷰를 쓰다가 아이템의 구성이 바뀔때, "아이템이 어디가 바뀌었지... 아... 몰라 notifyDataSetChanged!" 라는 생각을 하며 notifyDataSetChanged()를 호출하곤 해버린다. 물론 좋지 않은 일이지만.. 어쩔수 없다. 나는 멍청이니까. 하지만 이런 멍청한 코딩이 꽤 많았는지, 안드로이드에는 이러한 걸 도와주는 유틸이 있다. DiffUtil이라고 해서, 리사이클러뷰의 데이터 셋이 어떻게 바뀌었는지를 파악하고 그러한 변화를 리사이클러뷰에 던져줌으로써 프로그래머가 데이터 셋의 어느 부분이 구체적으로 변하였는지를 신경 쓰지 않게 도와준다. 자세한 내용은 뒤로 미루고, 어떤 결과가 나오는지, 어떻게 쓰는지부터 살펴보자. 이 움짤은, 5*5의 그리드 뷰에서 단순히 셔플을 하고..
-
안드로이드
Gradle : implementation VS compileOnly
안드로이드의 의존성을 관리하는 gradle을 이용하게 되면 습관적으로 implementation을 사용하게 된다. 그런데 여러 모듈을 개발하고 해당 모듈의 aar을 이용하여 개발을 만약 하게 된다면, 의존성 충돌때문에 빌드가 되지 않는 경우를 경험할 수 있을 것이다. 예를 들면 이렇다. 메인 프로젝트 : rxjava는 jar을 통해 implemetation, rxandroid는 aar을 통해 implementation, 그 외에 여러가지 jar, aar 파일을 implementation filetree를 통해 의존 서브 모듈 : rxjava와 rxandroid를 마찬가지로 jar과 aar을 통해 의존 이런 프로젝트에서 서브 모듈을 aar로 빌드한 뒤 메인프로젝트에 넣고 메인프로젝트를 빌드하면 rxjava..
안드로이드
-
안드로이드
Kotlin DSL을 이해해보자 - 1. 확장함수타입
TL; DR DSL을 만들 때 인자로 넣는 Person.() -> Unit 은 확장함수타입이다. 확장함수를 인자로 넘겨주기 때문에 간략한 코드를 만들 수 있다. Kotlin DSL을 간단하게 말하자면 gradle의 dependencies를 보면 된다 dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version") implementation("org.koin:koin-android:1.0.2") . . . } 이렇게 dependencies의 블록 안에 실행하고자 하는 코드를 한줄 한줄 '선언'처럼 적어두게 하여 '명령형'이 아닌 '선언형'으로 코딩하게 하는 것이다. (Kotlin in action, pg.479)..
-
안드로이드
헤더가 찰싹 달라 붙는 스크롤 뷰 (Sticky Scroll View)
Fixed view in scroll view 네이버 앱을 보면 이렇게, 검색창이 위로 올라가다가 맨 위에 도달하면 더이상 올라가지 않고 고정이 된다. 실제로 네이버 앱 내부적으로는 CollapsingToolbarLayout을 이용하고 있을 수도 있다. 하지만, 만약 단순히 뷰를 고정시키기만 하고싶거나, 툴바는 다른 이유로 따로 쓰고 싶을 경우에는 CollapsingToolbarLayout를 사용하지 못한다. 그래서 이번에는 스크롤 뷰 내부의 임의의 뷰를 천장에 찰싹 달라 붙게 하는 커스텀 뷰를 만들어 보기로 하자. 전체 코드는 https://github.com/5seunghoon/Sticky_Scroll_View_Example 에 있고, 이번에는 https://github.com/amarjain07/S..
-
안드로이드
Android DiffUtil
리사이클러뷰를 쓰다가 아이템의 구성이 바뀔때, "아이템이 어디가 바뀌었지... 아... 몰라 notifyDataSetChanged!" 라는 생각을 하며 notifyDataSetChanged()를 호출하곤 해버린다. 물론 좋지 않은 일이지만.. 어쩔수 없다. 나는 멍청이니까. 하지만 이런 멍청한 코딩이 꽤 많았는지, 안드로이드에는 이러한 걸 도와주는 유틸이 있다. DiffUtil이라고 해서, 리사이클러뷰의 데이터 셋이 어떻게 바뀌었는지를 파악하고 그러한 변화를 리사이클러뷰에 던져줌으로써 프로그래머가 데이터 셋의 어느 부분이 구체적으로 변하였는지를 신경 쓰지 않게 도와준다. 자세한 내용은 뒤로 미루고, 어떤 결과가 나오는지, 어떻게 쓰는지부터 살펴보자. 이 움짤은, 5*5의 그리드 뷰에서 단순히 셔플을 하고..
플러터
-
플러터
Flutter - 현재 위젯 캡쳐(캡처)
현재 위젯을 캡쳐하는 방법을 알아보자. 안드로이드였다면 onDraw를 썼을테지만.. 플러터엔 그런거 없다..! 다만, renderObject를 활용하면 된다. 전체 소스 코드는 https://github.com/5seunghoon/Flutter_Capture_Example 여기에 있다. 1. 먼저 import부터. import 'dart:io'; import 'dart:async'; import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'pac..
-
플러터
플러터 - Status bar만 남기고 App bar는 지우기
Appbar를 지우려고 return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: new AppBar(), body: Center( child: Text("Hi"), )), ); 이런 코드에서 appbar만 지우면 쓸대없게도 status bar도 같이 사라진다. 이럴땐, primary: true, appBar: EmptyAppBar(), body: Center( child: Text("Hi"), )); 이런식으로 EmptyAppBar를 넣어주고, class EmptyAppBar extends StatelessWidget implements PreferredS..
-
플러터
간단한 플러터 앱 - 2초마다 한번씩 랜덤한 이름 만들기
플러터를 처음 공부하게 되면 하게 되는 튜토리얼의 앱인 "랜덤 이름 제네레이터" 구글 코드 랩에 나와있는 이 앱을 간단하게 개선해보면서 Stream의 사용법을 익혀봅시다. https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#8 이 링크를 통해 "랜덤 이름 제네레이터"를 만들어 보았다는 가정 하에 글을 써보겠습니다. 자 그럼, 우리는 이 앱을 기반으로 기능 하나를 추가해 보도록 합시다. 추가해볼 기능은 바로, 제목에도 나와있듯이, 랜덤한 이름을 2초마다 한번씩 제네레이팅하는 기능입니다. 일단, Dart의 Stream에 대해 알아보기 전에, https://software-creator.tistory.com/13?category=681..
알고리즘
-
알고리즘
SW expert academy 1824 혁진이의 프로그램 검증
기본적인 풀이는 DFS이다. DP[i][j][memory][direct]는 "i, j의 위치에서 memory의 값을 메모리에 저장해놨을 때, direct로 프로그램이 진행되고 있는 상황에서의 프로그램이 끝날 수 있는 지의 여부"이다.그 결과값이 1이면 끝날 수 있고, 2이면 끝날 수 없음을 의미한다. 혁진이의 프로그램이 무한루프가 돈다는 것은, 같은 memory와 direct의 상황에서 같은 i,j를 방문했다는 것으로 체크하면 된다. #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include #inc..
-
알고리즘
SW expert academy 1238 Contact
#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; int len, start; int main() { for (int tc = 1; tc > from; cin >> to; adj[from].insert(to); } queue next; bool isVisit[101]; for (int i = 0; i < 101; i++) { isVisit[i] = false; } //isVisit[start] = true; next.push(start); next.pus..
-
알고리즘
SW expert academy 1227 미로2
#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; int len, start; int moves[4][2] = { {-1,0}, {0, -1}, {1, 0}, {0, 1} }; int arr[100][100]; set adj[100][100]; int main() { for (int tc = 1; tc > testcasenum; int starti, startj, endi, endj; for (int i = 0; i < 100; i++) { string ..
인기글
-
플러터
플러터의 위젯 (1) - Container, Child, Children
플러터의 모든 것은, 그 앱 자체를 포함해서, 위젯이다. 이러한 모양의 위젯은, 이러한 트리로 구성된다. Container의 하위로 위젯을 넣으려면 child이나 children에 넣어주면 된다. 이름에서 알수 있듯이, 하나만 넣으려면 child, 여러개면 children이다. A child property if they take a single child – for example, Center or Container A children property if they take a list of widgets – for example, Row, Column, ListView, or Stack. (https://flutter.dev/docs/development/ui/layout 에서 발췌) 여기서 알 수 ..
-
안드로이드
헤더가 찰싹 달라 붙는 스크롤 뷰 (Sticky Scroll View)
Fixed view in scroll view 네이버 앱을 보면 이렇게, 검색창이 위로 올라가다가 맨 위에 도달하면 더이상 올라가지 않고 고정이 된다. 실제로 네이버 앱 내부적으로는 CollapsingToolbarLayout을 이용하고 있을 수도 있다. 하지만, 만약 단순히 뷰를 고정시키기만 하고싶거나, 툴바는 다른 이유로 따로 쓰고 싶을 경우에는 CollapsingToolbarLayout를 사용하지 못한다. 그래서 이번에는 스크롤 뷰 내부의 임의의 뷰를 천장에 찰싹 달라 붙게 하는 커스텀 뷰를 만들어 보기로 하자. 전체 코드는 https://github.com/5seunghoon/Sticky_Scroll_View_Example 에 있고, 이번에는 https://github.com/amarjain07/S..
-
플러터
Flutter - 현재 위젯 캡쳐(캡처)
현재 위젯을 캡쳐하는 방법을 알아보자. 안드로이드였다면 onDraw를 썼을테지만.. 플러터엔 그런거 없다..! 다만, renderObject를 활용하면 된다. 전체 소스 코드는 https://github.com/5seunghoon/Flutter_Capture_Example 여기에 있다. 1. 먼저 import부터. import 'dart:io'; import 'dart:async'; import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'pac..
-
알고리즘
백준 3665 최종순위
풀이는 다음과 같다. 팀을 vertex, 팀의 우열관계를 edge로 하여 방향그래프를 만든다. 이때 주의할 점은 가능한 모든 edge를 다 넣는 것이다. 예를 들어, 4 3 2 1이 주어졌다고 하자(팀4가 1등, 팀1이 4등)그렇다면 방향그래프는 4 -> 34 -> 24 -> 1 3 -> 23 -> 1 2 -> 1 와 같이 6개의 edge로 구성되어 있어야 한다. 그 후 팀의 우선순위가 바뀌는 쌍을 입력받는다.이 쌍은 방향이 바뀌는 edge의 노드 쌍이다. 예를 들어, 위와 같은 그래프일때 (4, 1)(3, 2) 를 입력받았다면 4 -> 34 -> 24 1 와 같은 그래프로 바뀐다 그 후, 이 그래프를 위상정렬을 하여 팀의 등수를 나타내는 것이 이 문제의 풀이이다. From노드로부터 To노드로 연결되어 ..
-
안드로이드
안드로이드 Picture In Picture (PIP)
깃 헙 주소 : https://github.com/5seunghoon/PipExample PIP기능은 아래와 같다 이렇게 재생되던 동영상을, 홈키같은걸 눌리게 되면 이렇게 작은화면으로 전환되고, 다른 앱 위에서 동영상이 계속 재생될 수 있는 기능이다. 유튜브나 네이버TV등에서 자주 볼 수 있는 기능이다. 이를 간단하게 구현해보자. 먼저 깃헙 주소는 게시글의 최상단에 미리 적어놓았다. 1. 매니패스트의 액티비티 부분을 다음과 같이 수정하자 보면, android:resizeableActivity과 supportPictureInPicture이 설정되어 있는 것을 알 수 있다. 2. 액티비티 xml 수정 먼저 VideoView를 리니어 레이아웃의 최상단에 두고, 스크롤뷰를 그 밑에 둔 다음 그 스크롤뷰에 이것저..
-
안드로이드
Android Kotlin MVVM패턴으로 간단한 검색 앱 만들기 - 1. BaseView, BaseViewModel을 작성하여 MVVM의 토대 만들기
MVVM 패턴과 Kotlin으로 간단한 앱을 만드는 것에 대해 글을 써보려고 합니다. 저도 정리를 좀 하고, 다른 분들도 도움이 좀 되셨으면 하는 의미에서.. 일단 어떤 앱을 만들고자 하냐면, 간단하게 카카오 Api로 이미지 검색을 해서 그 내용을 화면에 리사이클러뷰로 그리드하게 쭉 뿌려주는 앱을 샘플로 만들어 볼 예정입니다. 이렇게요! 그 과정에서 MVVM패턴을 위한 Livedata, 통신을 위한 Retrofit + RxJava, 이미지를 뿌려주기 위한 Picasso 의존성주입을 위한 Koin, 그리고 com.android.support를 대채하는 AndroidX 를 활용해 볼 예정입니다. AndroidX에 관해서는 https://thdev.tech/google%20io/2018/05/12/Androi..
-
안드로이드
심플 프리뷰 메이커 개인정보 처리방침
1. '심플 프리뷰 메이커'는 이용자의 개인정보를 매우 중요하게 생각하며 각별히 주의를 기울여 처리하고 있습니다.다음과 같은 목적외에는 사용하지 않습니다. - 사진을 편집하고 저장 2. 정보 주체의 권리, 의무 및 그 행사방법 이용자는 개인정보 주체로서 다음과 같은 권리를 행사할 수 있습니다. ① 정보주체는 '심플 프리뷰 메이커'에 대해 언제든지 다음 각 호의 개인정보 보호 관련 권리를 행사할 수 있습니다. 1) 개인정보 열람요구2) 오류 등이 있을 경우 정정 요구3) 삭제요구4) 처리정지 요구 * '심플 프리뷰 메이커'는 앱 사용자의 사용정보를 수집 및 보유하지 않습니다. 3. 처리하는 개인정보의 항목 작성 ① '심플 프리뷰 메이커'은(는) 다음의 개인정보 항목을 처리하고 있습니다. 1) 사진파일의 접..
-
안드로이드
Android Action Mode
안드로이드에서 Text를 Select했을 때 나오는 메뉴에 뭔가 추가하고 싶을 수도 있다. 예를 들면, 이런식으로, Important를 꾹~ 눌려서 (Long press) Text를 Select한 뒤에 나오는 메뉴에서 '퀵번역'을 추가 하고 싶을 수 있다. 이런걸 구현하려고 하면 간단하게 함수 하나만 override하면 된다. @Override public void onActionModeStarted(final android.view.ActionMode mode) { Menu menu = mode.getMenu(); menu.add("퀵번역") .setEnabled(true) .setVisible(true) .setOnMenuItemClickListener(item -> { //해당 메뉴를 눌렸을 때 수..
-
잡다한 코딩
Webstorm 이용한 Spring boot + Vue.js 연동
정말 간단하다 spring boot 프로젝트에 src나 target과 같은 경로에 frontend폴더를 만들고 거기에 vue.js프로젝트가 들어가게 한다 그러니까, 그냥 프로젝트 만들때부터 이렇게 만들면 된다 (Users/venditz/Document/IdeaProject/springpractice04 가 스프링 프로젝트 폴더) 그러면 아래와 같은 프로젝트 구성이 된다 그 후에 frontend/config/index.js에서 빌드 부분을 이렇게 바꿔준다 그리고 터미널이든 cmd이든 frontend 폴더로 이동한 뒤 npm run build 해주면 이런게 뜬다 그럼 이제 아무것도 없던 src/main/resouces 폴더에 이러한 index 파일이 생성될거다 그럼 끝! 이제 스프링부트를 실행하고 127.0..
-
잡다한 코딩
[openGL][python3] 미니멀 태양계
결과물은 위와 같다. 태양, 지구, 명왕성, 그리고 지구를 회전하는 인공위성이 있다. 인공위성은 공전축이 매 회전마다 조금씩 바뀌고 명왕성은 공전궤도가 타원이다. 왼쪽위부터 태양계 전체를 보는 화면, 태양에서 12시 방향의 우주, 명왕성에서 본 지구, 지구의 한국에서 본 하늘 을 표현하고 있다. constant.py는 전역변수들을 저장하고 있다. 물론 이것도 과제다. main.pyfrom OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * from constant import * import math def drawSatellite(): global satelliteRevolveAxisCount global satelliteNowX..
-
플러터
플러터 - Status bar만 남기고 App bar는 지우기
Appbar를 지우려고 return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: new AppBar(), body: Center( child: Text("Hi"), )), ); 이런 코드에서 appbar만 지우면 쓸대없게도 status bar도 같이 사라진다. 이럴땐, primary: true, appBar: EmptyAppBar(), body: Center( child: Text("Hi"), )); 이런식으로 EmptyAppBar를 넣어주고, class EmptyAppBar extends StatelessWidget implements PreferredS..
-
플러터
간단한 플러터 앱 - 2초마다 한번씩 랜덤한 이름 만들기
플러터를 처음 공부하게 되면 하게 되는 튜토리얼의 앱인 "랜덤 이름 제네레이터" 구글 코드 랩에 나와있는 이 앱을 간단하게 개선해보면서 Stream의 사용법을 익혀봅시다. https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#8 이 링크를 통해 "랜덤 이름 제네레이터"를 만들어 보았다는 가정 하에 글을 써보겠습니다. 자 그럼, 우리는 이 앱을 기반으로 기능 하나를 추가해 보도록 합시다. 추가해볼 기능은 바로, 제목에도 나와있듯이, 랜덤한 이름을 2초마다 한번씩 제네레이팅하는 기능입니다. 일단, Dart의 Stream에 대해 알아보기 전에, https://software-creator.tistory.com/13?category=681..
-
안드로이드
Android Kotlin MVVM패턴으로 간단한 검색 앱 만들기 - 3. RxJava + Retrofit를 통한 네트워킹 및 옵저빙
이번 글에서는 Retrofit으로 네트워크 통신을 하고 그 결과값을 RxJava로 받아오는 과정을 수행해보겠습니다. 일단 Retrofit에 대해 간단히 알아보도록 하죠. Retrofit 저도 최근에 알았는데, 레트로핏 한글 문서가 있더라구요. http://devflow.github.io/retrofit-kr/ 길지 않으니 한번 정독하셔도 됩니다. 간단하게 레트로핏을 요약하자면 public interface GitHubService { @GET("/users/{user}/repos") Call listRepos(@Path("user") String user);} 이렇게 인터페이스 형태의 서비스를 먼저 만듭니다. 자바 어노테이션으로 @Get이나 @Post 등을 적어주고, 파라미터로 라우팅 정보를 적어줍니다...
-
안드로이드
Uri to path, path to Uri
절대경로 -> uri public Uri getUriFromPath(String filePath) { Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, "_data = '" + filePath + "'", null, null); cursor.moveToNext(); int id = cursor.getInt(cursor.getColumnIndex("_id")); Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id); return uri; } uri -> 절대경로 public String ..
-
안드로이드
Android Kotlin MVVM패턴으로 간단한 검색 앱 만들기 - 4. Livedata를 통한 데이터 바인딩
이번에는 저번 글에 이어서 Livedata를 이용하여 View 와 ViewModel간의 데이터 바인딩에 대해 글을 써보겠습니다. 저번 글에서도 설명한것처럼, View는 ViewModel 객체를 멤버로 가지고 있지만, ViewModel은 View의 객체를 가지고 있지 않습니다. 그럼, ViewModel에서 View의 함수를 호출하거나 View의 내용을 변경하거나, 혹은 Context나 Activity 객체의 함수를 호출해야 할 때는 어떻게 해야 할까요? 물론 Context를 이용하고 싶으면 AndroidViewModel을 상속하면 되지만, 지금은 넘어가도록 합시다. 해답은 바로 View가 ViewModel의 특정한 데이터를 Observing하고 있다가, 그 데이터가 변경될 때 View의 로직을 수행하면 됩..
-
안드로이드
Android Kotlin MVVM패턴으로 간단한 검색 앱 만들기 - 2. Koin을 통한 의존성 주입
의존성 주입.. Dependency injection ... 줄여서... DI.... 이걸 왜하느냐! 라고 물으시면.. 아주 간단하게, 테스팅을 위해서! 라고 답할 수 있지 않을까요..? 지금과 같은 MVVM패턴에서 뷰모델을 테스팅한다고 칩시다. 그럼 뷰모델을 테스팅하려면 뷰모델이 의존하고 있는 모델은.. 어떻게 만들어서 뷰모델에게 줘야 뷰모델을 테스팅 할 수 있을까요? 간단한 방법으로는 모델을 내부에서 생성하지 않고 생성자의 인자로 주는 것입니다. ViewModel{val model = Model()} 과 같이 하지 않고 ViewModel(val model){} 이렇게 그러면 뷰모델을 테스팅모듈에서 생성할 때 테스팅용 모델을 뷰모델의 생성자로 '주입' 해줌으로서 뷰모델을 테스팅하기 쉽게 할 수 있는 것..