Android 에서 양 방향 슬라이딩 효 과 를 실현 하 는 인 스 턴 스 코드
시작 하기 전에 실현 원 리 를 말씀 드 리 겠 습 니 다.한 Activity 의 구조 에 세 부분 이 필요 합 니 다.하 나 는 왼쪽 메뉴 의 구조 이 고 하 나 는 오른쪽 메뉴 의 구조 이 며 하 나 는 내용 의 구조 입 니 다.왼쪽 메뉴 는 화면 왼쪽 가장자리 에서 정렬 하고 오른쪽 메뉴 는 화면 오른쪽 가장자리 에서 정렬 한 다음 에 내용 레이아웃 이 전체 화면 을 차지 하고 왼쪽 메뉴 와 오른쪽 메뉴 위 에 눌 렀 다.사용자 가 손가락 을 오른쪽으로 미 끄 러 뜨 렸 을 때 오른쪽 메뉴 를 숨 기 고 왼쪽 메뉴 를 표시 한 다음 내용 레이아웃 의 위 치 를 이동 하면 왼쪽 메뉴 를 보 여 줍 니 다.마찬가지 로 사용자 의 손가락 이 왼쪽으로 미 끄 러 질 때 왼쪽 메뉴 를 숨 기 고 오른쪽 메뉴 도 내용 레이아웃 의 위 치 를 옮 겨 오른쪽 메뉴 를 보 여 주 는 것 입 니 다.원리 설명도 에서 보 듯 이:
원 리 를 소 개 했 으 니 우리 손 을 써 서 실현 합 시다.안 드 로 이 드 프로젝트 를 새로 만 듭 니 다.프로젝트 이름 은 BidirSlidingLayout 입 니 다.그리고 우리 의 가장 주요 한 BidirSlidingLayout 클래스 를 새로 만 듭 니 다.이 클래스 는 양 방향 슬라이딩 메뉴 기능 을 실현 하 는 핵심 클래스 입 니 다.코드 는 다음 과 같 습 니 다.
public class BidirSlidingLayout extends RelativeLayout implements OnTouchListener {
/**
* , 。
*/
public static final int SNAP_VELOCITY = 200;
/**
* , 。
*/
public static final int DO_NOTHING = 0;
/**
* , 。
*/
public static final int SHOW_LEFT_MENU = 1;
/**
* , 。
*/
public static final int SHOW_RIGHT_MENU = 2;
/**
* , 。
*/
public static final int HIDE_LEFT_MENU = 3;
/**
* , 。
*/
public static final int HIDE_RIGHT_MENU = 4;
/**
*
*/
private int slideState;
/**
* 。
*/
private int screenWidth;
/**
* 。
*/
private int touchSlop;
/**
* 。
*/
private float xDown;
/**
* 。
*/
private float yDown;
/**
* 。
*/
private float xMove;
/**
* 。
*/
private float yMove;
/**
* 。
*/
private float xUp;
/**
* 。 , 。
*/
private boolean isLeftMenuVisible;
/**
* 。 , 。
*/
private boolean isRightMenuVisible;
/**
* 。
*/
private boolean isSliding;
/**
* 。
*/
private View leftMenuLayout;
/**
* 。
*/
private View rightMenuLayout;
/**
* 。
*/
private View contentLayout;
/**
* View。
*/
private View mBindView;
/**
* 。
*/
private MarginLayoutParams leftMenuLayoutParams;
/**
* 。
*/
private MarginLayoutParams rightMenuLayoutParams;
/**
* 。
*/
private RelativeLayout.LayoutParams contentLayoutParams;
/**
* 。
*/
private VelocityTracker mVelocityTracker;
/**
* BidirSlidingLayout , touchSlop 。
*
* @param context
* @param attrs
*/
public BidirSlidingLayout(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
/**
* View。
*
* @param bindView
* View 。
*/
public void setScrollEvent(View bindView) {
mBindView = bindView;
mBindView.setOnTouchListener(this);
}
/**
* , -30.
*/
public void scrollToLeftMenu() {
new LeftMenuScrollTask().execute(-30);
}
/**
* , -30.
*/
public void scrollToRightMenu() {
new RightMenuScrollTask().execute(-30);
}
/**
* , 30.
*/
public void scrollToContentFromLeftMenu() {
new LeftMenuScrollTask().execute(30);
}
/**
* , 30.
*/
public void scrollToContentFromRightMenu() {
new RightMenuScrollTask().execute(30);
}
/**
* , 。
*
* @return true, false。
*/
public boolean isLeftLayoutVisible() {
return isLeftMenuVisible;
}
/**
* , 。
*
* @return true, false。
*/
public boolean isRightLayoutVisible() {
return isRightMenuVisible;
}
/**
* onLayout 、 、 。
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
//
leftMenuLayout = getChildAt(0);
leftMenuLayoutParams = (MarginLayoutParams) leftMenuLayout.getLayoutParams();
//
rightMenuLayout = getChildAt(1);
rightMenuLayoutParams = (MarginLayoutParams) rightMenuLayout.getLayoutParams();
//
contentLayout = getChildAt(2);
contentLayoutParams = (RelativeLayout.LayoutParams) contentLayout.getLayoutParams();
contentLayoutParams.width = screenWidth;
contentLayout.setLayoutParams(contentLayoutParams);
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
createVelocityTracker(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// ,
xDown = event.getRawX();
yDown = event.getRawY();
// DO_NOTHING
slideState = DO_NOTHING;
break;
case MotionEvent.ACTION_MOVE:
xMove = event.getRawX();
yMove = event.getRawY();
// , , 。
int moveDistanceX = (int) (xMove - xDown);
int moveDistanceY = (int) (yMove - yDown);
//
checkSlideState(moveDistanceX, moveDistanceY);
//
switch (slideState) {
case SHOW_LEFT_MENU:
contentLayoutParams.rightMargin = -moveDistanceX;
checkLeftMenuBorder();
contentLayout.setLayoutParams(contentLayoutParams);
break;
case HIDE_LEFT_MENU:
contentLayoutParams.rightMargin = -leftMenuLayoutParams.width - moveDistanceX;
checkLeftMenuBorder();
contentLayout.setLayoutParams(contentLayoutParams);
case SHOW_RIGHT_MENU:
contentLayoutParams.leftMargin = moveDistanceX;
checkRightMenuBorder();
contentLayout.setLayoutParams(contentLayoutParams);
break;
case HIDE_RIGHT_MENU:
contentLayoutParams.leftMargin = -rightMenuLayoutParams.width + moveDistanceX;
checkRightMenuBorder();
contentLayout.setLayoutParams(contentLayoutParams);
default:
break;
}
break;
case MotionEvent.ACTION_UP:
xUp = event.getRawX();
int upDistanceX = (int) (xUp - xDown);
if (isSliding) {
// ,
switch (slideState) {
case SHOW_LEFT_MENU:
if (shouldScrollToLeftMenu()) {
scrollToLeftMenu();
} else {
scrollToContentFromLeftMenu();
}
break;
case HIDE_LEFT_MENU:
if (shouldScrollToContentFromLeftMenu()) {
scrollToContentFromLeftMenu();
} else {
scrollToLeftMenu();
}
break;
case SHOW_RIGHT_MENU:
if (shouldScrollToRightMenu()) {
scrollToRightMenu();
} else {
scrollToContentFromRightMenu();
}
break;
case HIDE_RIGHT_MENU:
if (shouldScrollToContentFromRightMenu()) {
scrollToContentFromRightMenu();
} else {
scrollToRightMenu();
}
break;
default:
break;
}
} else if (upDistanceX < touchSlop && isLeftMenuVisible) {
// , ,
scrollToContentFromLeftMenu();
} else if (upDistanceX < touchSlop && isRightMenuVisible) {
// , ,
scrollToContentFromRightMenu();
}
recycleVelocityTracker();
break;
}
if (v.isEnabled()) {
if (isSliding) {
//
unFocusBindView();
return true;
}
if (isLeftMenuVisible || isRightMenuVisible) {
// ,
return true;
}
return false;
}
return true;
}
/**
* , , slideState 。
*
* @param moveDistanceX
*
* @param moveDistanceY
*
*/
private void checkSlideState(int moveDistanceX, int moveDistanceY) {
if (isLeftMenuVisible) {
if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX < 0) {
isSliding = true;
slideState = HIDE_LEFT_MENU;
}
} else if (isRightMenuVisible) {
if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX > 0) {
isSliding = true;
slideState = HIDE_RIGHT_MENU;
}
} else {
if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX > 0
&& Math.abs(moveDistanceY) < touchSlop) {
isSliding = true;
slideState = SHOW_LEFT_MENU;
contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
contentLayout.setLayoutParams(contentLayoutParams);
// , ,
leftMenuLayout.setVisibility(View.VISIBLE);
rightMenuLayout.setVisibility(View.GONE);
} else if (!isSliding && Math.abs(moveDistanceX) >= touchSlop && moveDistanceX < 0
&& Math.abs(moveDistanceY) < touchSlop) {
isSliding = true;
slideState = SHOW_RIGHT_MENU;
contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
contentLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
contentLayout.setLayoutParams(contentLayoutParams);
// , ,
rightMenuLayout.setVisibility(View.VISIBLE);
leftMenuLayout.setVisibility(View.GONE);
}
}
}
/**
* , 。
*/
private void checkLeftMenuBorder() {
if (contentLayoutParams.rightMargin > 0) {
contentLayoutParams.rightMargin = 0;
} else if (contentLayoutParams.rightMargin < -leftMenuLayoutParams.width) {
contentLayoutParams.rightMargin = -leftMenuLayoutParams.width;
}
}
/**
* , 。
*/
private void checkRightMenuBorder() {
if (contentLayoutParams.leftMargin > 0) {
contentLayoutParams.leftMargin = 0;
} else if (contentLayoutParams.leftMargin < -rightMenuLayoutParams.width) {
contentLayoutParams.leftMargin = -rightMenuLayoutParams.width;
}
}
/**
* 。 1/2, SNAP_VELOCITY,
* 。
*
* @return true, false。
*/
private boolean shouldScrollToLeftMenu() {
return xUp - xDown > leftMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
}
/**
* 。 1/2, SNAP_VELOCITY,
* 。
*
* @return true, false。
*/
private boolean shouldScrollToRightMenu() {
return xDown - xUp > rightMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
}
/**
* , 1/2, SNAP_VELOCITY,
* 。
*
* @return true, false。
*/
private boolean shouldScrollToContentFromLeftMenu() {
return xDown - xUp > leftMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
}
/**
* , 1/2, SNAP_VELOCITY,
* 。
*
* @return true, false。
*/
private boolean shouldScrollToContentFromRightMenu() {
return xUp - xDown > rightMenuLayoutParams.width / 2 || getScrollVelocity() > SNAP_VELOCITY;
}
/**
* VelocityTracker , VelocityTracker 。
*
* @param event
*
*/
private void createVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/**
* 。
*
* @return , 。
*/
private int getScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
int velocity = (int) mVelocityTracker.getXVelocity();
return Math.abs(velocity);
}
/**
* VelocityTracker 。
*/
private void recycleVelocityTracker() {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
/**
* 。
*/
private void unFocusBindView() {
if (mBindView != null) {
mBindView.setPressed(false);
mBindView.setFocusable(false);
mBindView.setFocusableInTouchMode(false);
}
}
class LeftMenuScrollTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
int rightMargin = contentLayoutParams.rightMargin;
// , , 。
while (true) {
rightMargin = rightMargin + speed[0];
if (rightMargin < -leftMenuLayoutParams.width) {
rightMargin = -leftMenuLayoutParams.width;
break;
}
if (rightMargin > 0) {
rightMargin = 0;
break;
}
publishProgress(rightMargin);
// , , 。
sleep(15);
}
if (speed[0] > 0) {
isLeftMenuVisible = false;
} else {
isLeftMenuVisible = true;
}
isSliding = false;
return rightMargin;
}
@Override
protected void onProgressUpdate(Integer... rightMargin) {
contentLayoutParams.rightMargin = rightMargin[0];
contentLayout.setLayoutParams(contentLayoutParams);
unFocusBindView();
}
@Override
protected void onPostExecute(Integer rightMargin) {
contentLayoutParams.rightMargin = rightMargin;
contentLayout.setLayoutParams(contentLayoutParams);
}
}
class RightMenuScrollTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
int leftMargin = contentLayoutParams.leftMargin;
// , , 。
while (true) {
leftMargin = leftMargin + speed[0];
if (leftMargin < -rightMenuLayoutParams.width) {
leftMargin = -rightMenuLayoutParams.width;
break;
}
if (leftMargin > 0) {
leftMargin = 0;
break;
}
publishProgress(leftMargin);
// , , 。
sleep(15);
}
if (speed[0] > 0) {
isRightMenuVisible = false;
} else {
isRightMenuVisible = true;
}
isSliding = false;
return leftMargin;
}
@Override
protected void onProgressUpdate(Integer... leftMargin) {
contentLayoutParams.leftMargin = leftMargin[0];
contentLayout.setLayoutParams(contentLayoutParams);
unFocusBindView();
}
@Override
protected void onPostExecute(Integer leftMargin) {
contentLayoutParams.leftMargin = leftMargin;
contentLayout.setLayoutParams(contentLayoutParams);
}
}
/**
* 。
*
* @param millis
* ,
*/
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
이상 의 코드 주석 은 이미 매우 상세 하 게 썼 으 니,내 가 다시 간단하게 설명 하 겠 다.먼저 onLayout()방법 에서 왼쪽 메뉴,오른쪽 메뉴 와 내용 레이아웃 의 인 자 를 각각 얻 고 내용 레이아웃 의 너 비 를 화면의 너비 로 다시 정의 하면 내용 레이아웃 이 아래 메뉴 레이아웃 을 덮 을 수 있 고 화면 도 오프셋 할 수 있 습 니 다.그리고 onTouch()방법 에서 터치 스크린 사건 을 감청 하여 사용자 의 손짓 의 도 를 판단 한다.여기에 몇 가지 미끄럼 상 태 를 미리 정 의 했 습 니 다.DONOTING 은 미끄럼 을 전혀 하지 않 았 다 고 밝 혔 습 니 다.SHOWLEFT_MENU 는 사용자 가 왼쪽 메뉴 에서 미끄러져 나 가 고 싶다 고 표시 합 니 다.SHOWRIGHT_MENU 는 사용자 가 오른쪽 메뉴 에서 미끄러져 나 가 고 싶다 고 표시 합 니 다.HIDELEFT_MENU 는 사용자 가 왼쪽 메뉴 를 숨 기 고 싶다 는 뜻 입 니 다.HIDERIGHT_MENU 는 사용자 가 오른쪽 메뉴 를 숨 기 고 싶다 고 표시 합 니 다.checkSlideState()방법 에서 사용자 가 어떤 미끄럼 동작 을 하고 싶 은 지 판단 하고 slidestate 변수 에 값 을 부여 한 다음 slidestate 값 에 따라 내용 레이아웃 을 어떻게 옮 기 는 지 결정 합 니 다.이 어 사용자 손가락 이 화면 을 떠 날 때 현재 미끄럼 거리 에 따라 후속 스크롤 방향 을 결정 하고 Left Menu ScrollTask 와 RightMenu ScrollTask 를 통 해 완전한 미끄럼 과정 을 완성 합 니 다.또한 미 끄 러 지 는 과정 에서 내용 구조 상의 사건 이 차단 되 고 주로 일련의 return 작업 을 통 해 이 루어 집 니 다.이 부분 에 대해 이해 하지 못 하 는 친 구 는 참고 하 시기 바 랍 니 다Android 는 소스 코드 의 측면 에서 사건 배포 메커니즘 의 해석 을 철저히 이해 합 니 다..그리고 set ScrollEvent 방법 을 살 펴 보 겠 습 니 다.이 방법 은 View 를 매개 변수 로 받 은 다음 에 이 View 에 touch 이 벤트 를 연결 합 니 다.이게 무슨 뜻 이 죠?콘 텐 츠 레이아웃 이 LinearLayout 이 라면 LinearLayout 의 touch 사건 을 감청 하여 오프셋 을 제어 할 수 있 습 니 다.그러나 콘 텐 츠 레이아웃 의 LinearLayout 에 ListView 가 추가 되 었 고 이 ListView 는 LinearLayout 전 체 를 가득 채 웠 다.이 럴 때 LinearLayout 는 더 이상 터치 되 지 않 을 것 이다.이 럴 때 우 리 는 touch 사건 을 ListView 에 등록 해 야 한다.setScrollEvent 방법 은 등록 인 터 페 이 스 를 제공 하 는 것 입 니 다.touch 이 벤트 는 들 어 오 는 View 에 등 록 됩 니 다.
다음 에 열거 나 새로 만 든 activitymain.xml 파일,다음 코드 추가:
<com.example.bidirslidinglayout.BidirSlidingLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bidir_sliding_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="@+id/left_menu"
android:layout_width="270dip"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:background="#00ccff"
android:visibility="invisible" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is left menu"
android:textColor="#000000"
android:textSize="28sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/right_menu"
android:layout_width="270dip"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#00ffcc"
android:visibility="invisible" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="This is right menu"
android:textColor="#000000"
android:textSize="28sp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/content"
android:layout_width="320dip"
android:layout_height="fill_parent"
android:background="#e9e9e9" >
<ListView
android:id="@+id/contentList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none"
android:cacheColorHint="#00000000" >
</ListView>
</LinearLayout>
</com.example.bidirslidinglayout.BidirSlidingLayout>
이 를 통 해 알 수 있 듯 이 저 희 는 사용자 정의 BidirSliding Layout 를 루트 레이아웃 으로 사용 한 다음 에 세 개의 키 레이아웃 을 각각 왼쪽 메뉴,오른쪽 메뉴 와 내용 의 레이아웃 으로 추가 하 였 습 니 다.왼쪽 메뉴 와 오른쪽 메뉴 에 텍스트 뷰 를 간단하게 넣 어서 텍스트 를 표시 하고 내용 레이아웃 에 ListView 를 넣 었 습 니 다.왼쪽 메뉴 와 부모 레이아웃 왼쪽 가장자리 가 정렬 되 고 오른쪽 메뉴 와 부모 레이아웃 오른쪽 가장자리 가 정렬 되 어야 합 니 다.마지막 으로 MainActivity 를 프로그램의 주 Activity 로 열거 나 만 듭 니 다.코드 는 다음 과 같 습 니 다.
public class MainActivity extends Activity {
/**
*
*/
private BidirSlidingLayout bidirSldingLayout;
/**
* ListView
*/
private ListView contentList;
/**
* ListView
*/
private ArrayAdapter<String> contentListAdapter;
/**
* contentListAdapter 。
*/
private String[] contentItems = { "Content Item 1", "Content Item 2", "Content Item 3",
"Content Item 4", "Content Item 5", "Content Item 6", "Content Item 7",
"Content Item 8", "Content Item 9", "Content Item 10", "Content Item 11",
"Content Item 12", "Content Item 13", "Content Item 14", "Content Item 15",
"Content Item 16" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bidirSldingLayout = (BidirSlidingLayout) findViewById(R.id.bidir_sliding_layout);
contentList = (ListView) findViewById(R.id.contentList);
contentListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,
contentItems);
contentList.setAdapter(contentListAdapter);
bidirSldingLayout.setScrollEvent(contentList);
}
}
여기 서 우 리 는 ListView 에 몇 개의 데 이 터 를 채 우 고 findView ById()방법 으로 BidirSliding Layout 대상 을 얻 은 다음 에 setScrollEvent()방법 을 호출 하여 ListView 를 연결 하면 왼쪽 메뉴 와 오른쪽 메뉴 를 좌우 로 미 끄 러 뜨 릴 수 있 습 니 다.자,모든 인 코딩 작업 이 완료 되 었 습 니 다.이제 프로그램 을 실행 합 시다.효 과 는 다음 그림 과 같 습 니 다.
그래도 괜 찮 은 것 같은 데!그리고 더 중요 한 것 은 앞으로 우 리 는 프로젝트 의 어느 곳 에서 든 양 방향 슬라이딩 메뉴 기능 을 쉽게 추가 할 수 있 습 니 다.다음 과 같은 두 단계 만 있 으 면 됩 니 다.
1.Acitivty 의 layot 에 사용자 정의 BidirSlidingLayout 레이아웃 을 도입 하고 이 레이아웃 에 세 개의 직접 하위 요 소 를 추가 합 니 다.
2.Activity 에서 set ScrollEvent 방법 을 통 해 View 에 touch 이 벤트 를 등록 합 니 다.
이렇게 되면 1 분 동안 양 방향 슬라이딩 메뉴 기능 이 타당 하 다.
자,오늘 설명 은 여기 서 마 치 겠 습 니 다.궁금 한 분 은 아래 에 메 시 지 를 남 겨 주세요.
원본 다운로드,여 기 를 클릭 하 세 요.
버튼 이 있 는 버 전 다운로드,여 기 를 클릭 하 세 요.
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.