simpleWEB에 들어간 클래스/위젯
class, component on the simpleWEB
- WebView
- ProgessBar
- Intent
- EditText
- OptionMenu
- ContextMenu
- Thread






AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/> <!-- 인터넷 권한 부여 --> <application android:usesCleartextTraffic="true"> <!-- 텍스트URL을 무조건 허용함 -->
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="http://www.google.com"
android:ems="10"
android:selectAllOnFocus="true"
android:id="@+id/urledittext"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:imeOptions="actionUnspecified|actionSearch"
tools:visibility="visible"
android:textColorLink="#00BCD4"
android:textColorHighlight="#00BCD4"
android:textCursorDrawable="@color/colorPrimary"/>
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="true"
android:indeterminateTint="#00D8FF"
android:progress="25"
android:layout_width="0dp"
android:layout_height="14dp"
android:id="@+id/progressbar"
app:layout_constraintTop_toBottomOf="@+id/urledittext"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<WebView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/webview"
app:layout_constraintTop_toBottomOf="@+id/progressbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
main.xml (option menu)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="주 사이트"
android:id="@+id/site">
<menu
>
<item
android:title="SHA Computing"
android:id="@+id/action_sha"/>
<item
android:title="Google"
android:id="@+id/action_google"/>
<item
android:title="NAVER"
android:id="@+id/action_naver"/>
</menu>
</item>
<item
android:title="개발자 정보 "
android:id="@+id/developer">
<menu
>
<item
android:title="전화하기"
android:id="@+id/action_call"/>
<item
android:title="문자 보내기 "
android:id="@+id/action_send_text"/>
<item
android:title="이메일 보내기 "
android:id="@+id/action_email"/>
</menu>
</item>
<item
android:title="Home"
android:id="@+id/action_home"
android:icon="@drawable/ic_home_black_24dp"
app:showAsAction="ifRoom"/>
<item
android:title="앱 종료"
android:id="@+id/action_exit"/>
</menu>
context.xml (Context menu)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="페이지 공유"
android:id="@+id/action_share"/>
<item
android:title="기본 브라우저에서 열기 "
android:id="@+id/action_browser"/>
</menu>
MainActivity.kt
package com.example.simpleweb
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.util.Log
import android.view.ContextMenu
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.inputmethod.EditorInfo
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.ActionBar
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.*
import java.lang.Thread.sleep
class MainActivity : AppCompatActivity() {
private var lastTimeBackPressed:Long =-1500
private var isRunning=true
// 옵션 메뉴 메소드 재정의
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main,menu) // 메뉴 리소스를 지정한다. <매개변수 main객체도 인자로 보낸다>
return true // true를 반환하면 액티비티에 옵션 메뉴가 있다고 인식함
}
// 옵션 메뉴 아이템 메소드 재정의 <아이템 클릭될 때 호출>
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item?.itemId) { // item객체의 itemid필드는 사용자가 아이템을 선택할 때마다 값이 바뀜
R.id.action_google, R.id.action_home -> {
urledittext.setText("http://www.google.com")
webview.loadUrl("http://www.google.com")
return true
}
R.id.action_naver -> {
urledittext.setText("http://www.naver.com")
webview.loadUrl("http://www.naver.com")
return true
}
R.id.action_sha -> {
urledittext.setText("http://shacoding.com")
webview.loadUrl("http://shacoding.com")
return true
}
R.id.action_call -> {
val intent = Intent(Intent.ACTION_DIAL) // 다이얼창으로 이동하는 인텐트 기능
// Uri.parse메소드를 사용해서 전화번호 데이터를 가져옴
intent.data = Uri.parse("tel:1234-5678")
// 다이얼창으로 이동할 수 있는 액티비티(앱)을 찾음
// 있으면 다이얼창으로 이동
if (intent.resolveActivity(packageManager) != null)
startActivity(intent)
return true
}
R.id.action_send_text -> {
sendSMS("1234-5678", "HI")
return true
}
R.id.action_email -> {
email("cse@shacoding.com", "hi", "hi")
return true
}
R.id.action_exit -> {
finish()
return true
}
}
return super.onOptionsItemSelected(item) // 이외의 경우는 원래 메소드를 호출하는것이 일반적임
}
// 컨텍스트 메뉴 메소드 재정의
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
super.onCreateContextMenu(menu, v, menuInfo) // 컨텍스트 메뉴 만들기 위한 준비
menuInflater.inflate(R.menu.context,menu) // 메뉴 리소스를 지정한다. <매개변수 main객체도 인자로 보낸다>
}
// 컨텍스트 메뉴 아이템 메소드 재정의 <아이템 클릭될 때 호출>
override fun onContextItemSelected(item: MenuItem): Boolean {
when(item?.itemId){
R.id.action_share->{
share(webview.url)
return true
}
R.id.action_browser->{
browse(webview.url)
return true
}
}
return super.onOptionsItemSelected(item) // 이외의 경우는 원래 메소드를 호출하는것이 일반적임
}
// 뒤로 가기 눌렀을 때 호출되는 메소드 재정의
override fun onBackPressed() {
if(webview.canGoBack()) // 웹뷰가 뒤로 갈 페이지가 있다면
webview.goBack() // 뒤로 간다
else{
if(System.currentTimeMillis()-lastTimeBackPressed<=1500) // '이전 버튼' 두 번 클릭 시 앱 종료
finish()
lastTimeBackPressed=System.currentTimeMillis()
toast("이전 버튼을 한 번 더 누르면 종료됩니다!")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 웹뷰 기본 세팅
webview.apply {
settings.javaScriptEnabled = true // 자바스크립트 기능을 동작하게 하기
// (페이지를 뜨게하는) WebViewClient를 부모로 하는 무명 클래스 정의 및 인스턴스화
webViewClient = object : WebViewClient() {
// URL접속할 때 호출되는 메소드
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
progressbar.setVisibility(View.VISIBLE)
return super.shouldOverrideUrlLoading(view, request)
}
// 페이지 접속 마치면 호출되는 메소드
override fun onPageFinished(view: WebView?, url: String?) {
urledittext.setText(webview.url)
progressbar.setVisibility(View.GONE)
}
}
// 쓰레드 설정 (에딧 텍스트 보였다 안 보였다 하기)
val thread=ThreadClass()
thread.start()
webview.loadUrl("http://www.google.com") // 웹뷰에 지정 페이지를 연결
// 객체는 에딧 텍스트에 글자가 입력될 때마다 호출
urledittext.setOnEditorActionListener { _, actionId, _ ->
// 인자로 (반응한 뷰,키보드 버튼ID,이벤트)를 넘겨줌
// 아직 <에딧 텍스트에 반응한 뷰 >없고 이벤트 처리된 것도 없음
// 오직 키보드 버튼(ID:actionId) 만 제대로 인자로 넘겨주면 됨!! (나머지는 _)
if (actionId == EditorInfo.IME_ACTION_SEARCH) { // 키보드 버튼이 search버튼과 같다면
webview.loadUrl((urledittext.text).toString()) // url연결
urledittext.setText(webview.url)
true // true반환
} else {
false
} // 아니면 계속 false반환
}
// 웹뷰에 컨텍스트 메뉴 등록
registerForContextMenu(webview)
}
}
inner class ThreadClass:Thread(){
override fun run(){
var lasty=0
while(isRunning){
SystemClock.sleep(100)
runOnUiThread{
if(webview.getScrollY()==0)
urledittext.visibility=View.VISIBLE
else if(webview.getScrollY()>1000){
// 현재y랑 이전y랑 다를 때 동작 <스크롤 이벤트>
if(webview.getScrollY()!=lasty){
if(lasty-webview.getScrollY()>=100) // 스크롤을 올릴 때 동작 [ 현재 스크롤 Y < 이전 스크롤 Y ]
// 현재와 이전 사이에 100만큼 간격을 준 이유는 미세한 반응에도 동작하면 UX가 안 좋기 때문
urledittext.visibility=View.VISIBLE
else if(webview.getScrollY()-lasty>=100)// 스크롤을 내릴 때 동작
urledittext.visibility=View.GONE
lasty=webview.getScrollY()
}
}
}
}
}
}
// 프로그램이 종료될 때 실행되는 메소드 재정의
// isRunning에 false를 주어서 스레드를 종료한다
override fun onDestroy() {
super.onDestroy()
isRunning=false
}
}