Android – simpleWEB(웹뷰 응용) 레퍼런스 with. 코틀린

simpleWEB에 들어간 클래스/위젯

class, component on the simpleWEB

  • WebView
  • ProgessBar
  • Intent
  • EditText
  • OptionMenu
  • ContextMenu
  • Thread
edittext + webview
progressbar (indeterminate)
Option menu
Context Menu
Intent(share option) by Anko
Hide Progressbar when scrolling down

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
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *