일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 백엔드
- arrow function
- pwnable.tw
- 한국정보보호산업협회
- 한국정보보호산업협회기자단
- 디오판투스 알고리즘
- function scope
- 덧셈 암호
- 곱셈 암호
- 호이스팅
- 개인정보안전성
- 모듈러 연산
- 웹 프레임워크
- Writeup
- 확장 유클리드 알고리즘
- 유클리드_알고리즘
- 국가인적자원개발컨소시엄
- 포너블
- package-lock.json
- 가명정보처리
- 한국산업인력공단
- 개인정보보호교육
- 개인정보보호위원회
- 마감임박
- 무료교육
- node.js
- package.json
- 동적타이핑
- 백엔드입문
- 개인정보보호
- Today
- Total
짱짱해커가 되고 싶은 나
06-3. 뷰 컨테이너 본문
* View container
: ViewGroup 클래스 하위의 위젯 중 레이아웃을 제외한 것으로 다른 위젯을 담는 컨테이너 역할을 수행
* ScrollView
: 수직으로 스크롤 하는 기능
스크롤뷰에는 단 하나의 위젯만 넣을 수 있다. 따라서 스크롤 뷰 안에 리니어레이아웃을 1개 넣고, 리니어레이아웃 안에 원하는 것들을 여러 개 넣는 식으로 사용한다.
전체 화면을 스크롤 하기 위해 레이아웃 전체가 스크롤뷰에 싸여 있어 xmlns도 스크롤뷰에 정의된다.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="button1"/>
</LinearLayout>
</ScrollView>
* HorizontalScrollView
: 수평으로 스크롤 하는 기능, 마찬가지로 단 하나의 위젯만 가능
* SlidingDrawer
: 위젯을 서랍처럼 열어서 보여주거나 닫아서 감추는 기능(버튼을 누르면 쭉 올라옴 다시 누르면 내려가서 닫힘)
슬라이딩도어의 handle 속성에 지정된 이름과 슬라이딩드로어의 손잡이 역할인 버튼의 id가 동일해야한다.
그리고 슬라이딩드로어의 content 속성에 지정된 이름과 리니어레이아웃의 id도 동일해야 한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:text="여기는 서랍 밖입니다."
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<SlidingDrawer
android:layout_width="match_parent"
android:layout_height="match_parent"
android:content="@+id/content"
android:handle="@+id/handle">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/handle"
android:text="서랍 손잡이"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/content"
android:background="#00ff00"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="여기는 서랍 안입니다"/>
</LinearLayout>
</SlidingDrawer>
</LinearLayout>
* ViewFlipper
: 여러 개의 위젯을 배치하고 필요에 따라 화면을 왼쪽이나 오른쪽으로 밀어서 하나의 위젯씩 화면에 보여주는 방식
한 번에 보여줄 위젯이 여러개일 경우 뷰플리퍼 안에 레이아웃을 여러 개 넣고 각 레이아웃에 필요한 위젯을 배치한다.
- showPrevious() : 이전 위젯을 보여줌 = 오른쪽으로 밀기
- showNext() : 다음 위젯을 보여줌 = 왼쪽으로 밀기
- setFlipInterval() : 밀리초 단위로 화면 넘김 간격 설정 (시간 설정 안하면 화면 안 넘어가유~)
- startFlipping() : 화면 넘김 시작
- stopFlipping() : 화면 넘김 정지
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이전화면"/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="다음화면"/>
</LinearLayout>
<ViewFlipper
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewFlipper">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0000">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000ff">
</LinearLayout>
</ViewFlipper>
</LinearLayout>
ViewFlipper는 java와 함께 사용되야 한다. xml만 있으면 아무런 작동을 하지 않는다.
package com.example.widget4;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CalendarView;
import android.widget.Chronometer;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.MultiAutoCompleteTextView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.ViewFlipper;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn1, btn2;
final ViewFlipper viewFlipper;
btn1 = (Button)findViewById(R.id.btn1);
btn2 = (Button)findViewById(R.id.btn2);
viewFlipper = (ViewFlipper)findViewById(R.id.viewFlipper);
btn1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
viewFlipper.showPrevious();
}
});
btn2.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
viewFlipper.showNext();
}
});
}
}
viewFlipper앞에 final을 붙힌 이유는 내부 클래서에서 접근하기 위해서다.
* TabHost
: 각 탭을 클릭할 때마다 해당 화면이 나오도록 설정하는 뷰 컨테이너 (ex. 인터넷 익스플로러 상단 탭)
탭 호스트 - 리니어레이아웃(탭 위젯, 프레임 레이아웃) 의 형태로 구성된다.
탭호스트, 탭 위젯, 프레임레이아웃은 id가 지정되어 있는데 이 지정된 id를 변경하지 말고 그대로 사용해야만 안드로이드가 탭호스트의 구성을 인식한다. (tabhost, tabs, tabcontent)
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@android:id/tabs">
</TabWidget>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/tabcontent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tabSong"
android:background="#f00000"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tabArtist"
android:background="#f0f000"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tabAlbums"
android:background="#f000ff"
android:orientation="horizontal">
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
xml에서 framelayout에 tabcontent를 만들어 놓는다.
+ 탭을 아래에 놓고 싶으면 위치를 바꾸면 되는데 이 때 FrameLayout 에서 layout_weight="1"로 설정해야한다.
package com.example.widget4;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.TabActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.style.TabStopSpan;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CalendarView;
import android.widget.Chronometer;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.MultiAutoCompleteTextView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.ViewFlipper;
public class MainActivity extends TabActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabHost = getTabHost();
TabHost.TabSpec tabSpecSong = tabHost.newTabSpec("SONG").setIndicator("음악별");
tabSpecSong.setContent(R.id.tabSong);
tabHost.addTab(tabSpecSong);
TabHost.TabSpec tabSpecArtist = tabHost.newTabSpec("ARTIST").setIndicator("가수별");
tabSpecArtist.setContent(R.id.tabArtist);
tabHost.addTab(tabSpecArtist);
TabHost.TabSpec tabSpecAlbum = tabHost.newTabSpec("ALBUM").setIndicator("앨범별");
tabSpecAlbum.setContent(R.id.tabAlbums);
tabHost.addTab(tabSpecAlbum);
tabHost.setCurrentTab(0);
}
}
그리고 자바에서 탭을 추가하고 탭 컨탠트를 연결하는 과정을 수행한다.
이때 주의할 점은 상속받는게 TabActivity다~
먼저 TabHost 변수를 생성하고 TabSpec을 만든다. 탭스펙은 탭을 구성하는 요소들의 집합으로 볼 수 있다.
* 액션바
액션바를 구현할 때는 fragment를 사용하는 것이 좋다. 프래그먼트는 액티비티보다 작은 단위의 화면이라고 볼 수 있다. 프래그먼트를 사용하면 대형 화면에서 액티비티 화면을 분할해서 표현할 수 있고, 소형화면에서는 실행 중에 화면을 동적으로 추가하거나 제거하는데 활용된다.
액션바를 XML없이 탭 호스트처럼 사용할 수 있는 방법을 공부할 것이다. (진심 개복잡;;;)
package com.example.widget4;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity implements androidx.appcompat.app.ActionBar.TabListener {
androidx.appcompat.app.ActionBar.Tab tabSong;
androidx.appcompat.app.ActionBar.Tab tabArtist;
androidx.appcompat.app.ActionBar.Tab tabAlbum;
MyTabFragment myFrags[] = new MyTabFragment[3];
@SuppressLint("WrongConstant")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
androidx.appcompat.app.ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tabSong = bar.newTab();
tabSong.setText("음악별");
tabSong.setTabListener(this);
bar.addTab(tabSong);
tabArtist = bar.newTab();
tabArtist.setText("가수별");
tabArtist.setTabListener(this);
bar.addTab(tabArtist);
tabAlbum = bar.newTab();
tabAlbum.setText("앨범별");
tabAlbum.setTabListener(this);
bar.addTab(tabAlbum);
}
@Override
public void onTabSelected(androidx.appcompat.app.ActionBar.Tab tab, FragmentTransaction ft) {
MyTabFragment myTabFrag = null;
if(myFrags[tab.getPosition()] == null){
myTabFrag = new MyTabFragment();
Bundle data = new Bundle();
data.putString("tabName", tab.getText().toString());
myTabFrag.setArguments(data);
myFrags[tab.getPosition()] = myTabFrag;
}
else{
myTabFrag = myFrags[tab.getPosition()];
}
ft.replace(android.R.id.content, myTabFrag);
}
@Override
public void onTabUnselected(androidx.appcompat.app.ActionBar.Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(androidx.appcompat.app.ActionBar.Tab tab, FragmentTransaction ft) {
}
public static class MyTabFragment extends androidx.fragment.app.Fragment{
String tabName;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle data = getArguments();
tabName = data.getString("tabName");
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceSate){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
LinearLayout baseLayout = new LinearLayout(super.getActivity());
baseLayout.setOrientation(LinearLayout.VERTICAL);
baseLayout.setLayoutParams(params);
if(tabName == "음악별") baseLayout.setBackgroundColor(Color.RED);
if(tabName == "가수별") baseLayout.setBackgroundColor(Color.GREEN);
if(tabName == "앨범별") baseLayout.setBackgroundColor(Color.BLUE);
return baseLayout;
}
}
}
우선 가장 먼저 onTabSelected, onTabUnselected, onTabReselected 함수를 오버라이드 해야하기 때문에 ActionBar.TabListener 인터페이스를 구현해야한다. 그리고 전역변수로 ActioBar.Tab 과 MyTabFragment(화면 클래스 임의로 만든거) 배열을 선언한다.
액션바를 얻어오고 액션바의 모드를 NAVIGATION_MODE_TABS로 설정한다. 이 모드는 액션바에 여러 개의 탭을 배치하여 페이지를 전환할 수 있다. 그리고 아까 만들었던 각 탭마다 글자와 리스너를 설정하고 addTab()을 이용해 액션바에 추가한다.
(롤리팝 이후로는 내비게이션 모드를 사용하지 않을 것을 권고하지만 현재도 많이 사용되고 있음)
아까 가져온 3개의 메소드 중 Selected만 오버라이딩을 할 것이다. 이 부분을 보기 전에 여기서 사용할 클래스인 MyTabFragment부터 보자. Fragment를 상속받는 클래스이고 Fragment 클래스에서 onCreat() 함수는 초기화 리소스가 들어있는 곳인데 이 함수를 오버라이딩할 것이다. tabName은 선택된 탭의 텍스트를 받아서 프레그먼트의 tabName의 값으로 저장하는 부분이다. onCreateView는 프레그먼트에 나타날 화면을 구성하고 최종적으로 view로 반환한다. 이제 selected 함수를 보면 지금 만들었던 MyTabFragment 클래스를 이용할 것인데 여기서 현재 선택된 화면으로 사용된다. 만약에 선택한 탭이 기존에 한 번도 선택된 적이 없는 탭이라면 포지션이 Null일테고 프레그먼트를 생성하여 프래그먼트 배열에 넣고 새로운 프레그먼트를 생성한다. 그리고 이미 썼던 프레그먼트이면 만들어 놓은 걸 재사용하고 replace를 이용해 프레그먼트를 화면에 출력한다.
* WebView
: 사용자가 웹브라우저 기능을 앱 안에 직접 표현할 수 있는 위젯
프로젝트 : WebView를 이용해서 웹브라우저 생성
EditText 1개.- url 입력
Button 2개 (이동, 이전)
아이콘 & 로고 수정
<activity_main.xml>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/tabhost"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:layout_margin="5dp"
android:id="@+id/editText"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="URL을 입력하세요."
android:singleLine="true"
android:layout_width="match_parent">
</EditText>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:id="@+id/btn1"
android:text="이동">
</Button>
<Button
android:layout_margin="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn2"
android:text="이전">
</Button>
</LinearLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webView"/>
</LinearLayout>
edittext랑 버튼이 한 줄을 꽉 채우게 하기 위해서 텍스트에 weight=1을 줬다.
<MainActivity.java>
package com.example.widget4;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
EditText editText;
Button btn1, btn2;
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setIcon(R.drawable.ic_logo_foreground);
editText = (EditText)findViewById(R.id.editText);
btn1 = (Button)findViewById(R.id.btn1);
btn2 = (Button)findViewById(R.id.btn2);
webView = (WebView)findViewById(R.id.webView);
webView.setWebViewClient(new CookWebViewCleint());
WebSettings webset = webView.getSettings();
webset.setBuiltInZoomControls(true);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.loadUrl(editText.getText().toString());
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.goBack();
}
});
}
class CookWebViewCleint extends WebViewClient{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
}
}
WebView를 사용할 때는 우선 WebViewCleint를 상속받는 클래스를 하나 생성한다.
그리고 shouldOverrideUrLoading()을 오버라이딩한다. (안드로이드스튜디오의 override methods를 선택하면 편하게 오버라이딩할 메소드를 선택할 수 있다) 그런데 여기서는 굳이 바꿀게 없어서 수정하지 않아도 된다.
onCreate()에서 webview에 wetWebViewCleint로 아까 만들었던 클라이언트 클래스 객체를 생성해서 준다.
그리고 WebSettings를 만들어서 Zoom버튼을 만든다. (화면 확대/축소)
그런데 줌버튼이 도대체 어디에 생긴건지 모르겠다...ㅠ
이동 버튼은 loadUrl()을 이용해 웹뷰의 주소를 이동시키고 이전 버튼은 goBack()을 이용해 이전페이지로 이동한다.
<AndroidMainfest.xml>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.widget4">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_logo"
android:label="쿡북 웹브라우저"
android:roundIcon="@mipmap/ic_logo_round"
android:logo="@drawable/flower4"
android:supportsRtl="true"
android:theme="@style/Theme.Widget4">
<activity android:name=".MainActivity"
android:label="간단 웹브라우저">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
mainfest에서 인터넷을 사용할 수 있는 퍼미션을 준다.
그리고 로고(밖에서 보이는 앱 아이콘), 라벨(웹 정보로 봤을 때 보이는 이름)을 설정한다.
<MainActivity>에서 설정한 label은 실제 밖에서 보이는 앱의 이름 + 실행 화면 상단에 나오는 타이틀이다.
아이콘은 화면 상단에 나오는 건데 이렇게 설정했을 때 보이지가 않아서 ㅠ .MainActivity에서 추가했다.
의문점1. 아직도 아이콘이 왼쪽에 촥 붙어있는 예쁜 모양이 되지 않는다 ㅠ
의문점2. 교재에서는 xml 코드에서 그냥 icon속성 값으로 설정해도 잘 되는데 왜 나는 안되는걸까 ㅠㅠ
의문점3. 줌버튼은 도대체 어디에 있는 것인가
-> 글자를 누르면 나온다.
아이콘..에 대해 아시는 분이 있다면 알려주시길 ㅠㅠㅠ
'모바일' 카테고리의 다른 글
07-1. 메뉴 (0) | 2021.02.20 |
---|---|
06-4. 뷰 컨테이너 연습 (0) | 2021.02.19 |
06-2. 기타 위젯 (0) | 2021.02.17 |
06-1. 시간 관련 위젯 (0) | 2021.02.17 |
05-1. 레이아웃 (0) | 2021.02.17 |