잡동사니

반응형

질문

0. Problem

질문은 하단 시트 조각에서 button을 클릭하여 Webview-Fragment에서 링크를 열 목적으로 데이터 바인딩 라이브러리를 구현하는 아이디어를 제공했습니다.

다른 질문 ( 링크) ,하지만 WebView는 해당 Bottom Sheet Fragment에서 button을 클릭 할 때 새 URL을로드하지 않습니다. 콘솔에서 button을 클릭하고 LiveData가 변경되었다는 피드백을 받았습니다.그래서 LiveData가 변경되면 WebView가 자동으로 다시로드한다고 생각했지만 그렇지 않은 것 같습니다 ... 그래서 내 오류가 표시되지 않고 모든 것을 올바르게 구현했는지 확실하지 않습니다.

누군가가 나를 도울 수 있기를 바랍니다.


1. Respective Classes

1.1. WebViewFragment

    class WebviewFragment : Fragment() {

    private lateinit var webView: WebView

    companion object {
        fun newInstance() = WebviewFragment()
    }

    private lateinit var viewModel: WebViewViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val binding: FragmentMainWebviewBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_main_webview, container, false)
        viewModel = ViewModelProvider(this).get(WebViewViewModel::class.java)

        binding.webViewModel = viewModel
        binding.lifecycleOwner = this
        return binding.root
    }

    @SuppressLint("SetJavaScriptEnabled", "JavascriptInterface")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        webView = webViewMain
        webView.settings.javaScriptEnabled = true
    }
}

1.2. WebViewModel

    class WebViewViewModel : ViewModel() {

    val webViewUrl = MutableLiveData<String>().apply{ value = "file:///android_asset/html_files/gallery_page.html" }

    companion object WebViewUrlLoader {
        @BindingAdapter("loadUrl")
        @JvmStatic
        fun  WebView.setUrl(url: String) {
            this.loadUrl(url)
        }
    }
}

1.3. WebView Layout (XML)

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
            name="webViewModel"
            type="com.example.ui.main.webview.WebViewViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/main_screen_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainFragmentGalleryView"
        >
        <WebView
            android:id="@+id/webViewMain"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:loadUrl="@{webViewModel.webViewUrl}"
            android:paddingBottom="52dp" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

1.4. BottomSheet Fragment

class BottomSheetFragment : BottomSheetDialogFragment() {

    private var fragmentView: View? = null
    private lateinit var viewModel: WebViewViewModel

    companion object {
        fun newInstance() = BottomSheetFragment()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        fragmentView = inflater.inflate(R.layout.view_modal_bottom_sheet, container, false)
        return fragmentView
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProvider(this).get(WebViewViewModel::class.java)
        initView()
    }

    override fun getTheme(): Int {
        return R.style.Theme_NoWiredStrapInNavigationBar
    }

    private val mBottomSheetBehaviorCallback: BottomSheetCallback = object : BottomSheetCallback() {
        var isBottomSheetUp = false
        override fun onSlide(bottomSheet: View, slideOffset: Float) {
            //TODO("Not yet implemented")
        }

        override fun onStateChanged(bottomSheet: View, newState: Int) {
            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                isBottomSheetUp = false
                dismiss()
            } else isBottomSheetUp = true
        }

    }

    override fun setupDialog(dialog: Dialog, style: Int) {
        //super.setupDialog(dialog, style)
        val contentView =
            View.inflate(context,
                R.layout.view_modal_bottom_sheet, null)
        dialog.setContentView(contentView)
        val layoutParams =
            (contentView.parent as View).layoutParams as CoordinatorLayout.LayoutParams
        val behavior = layoutParams.behavior
        if (behavior != null && behavior is BottomSheetBehavior<*>) {
            behavior.setBottomSheetCallback(mBottomSheetBehaviorCallback)
        }
    }

    private fun initView() {

        action_my_pictures.setOnClickListener {
            viewModel.webViewUrl.value = "https://www.google.com/"
            Log.d("BottomSheet", "Button 1 Clicked ${viewModel.webViewUrl.value}")
        }
        action_favorites.setOnClickListener {
            viewModel.webViewUrl.value = "https://www.hotmail.de/"
            Log.d("BottomSheet", "Button 2 Clicked ${viewModel.webViewUrl.value}")

        }
        action_ranking.setOnClickListener {
            viewModel.webViewUrl.value = "https://amazon.com/"
            Log.d("BottomSheet", "Button 3 Clicked ${viewModel.webViewUrl.value}")

        }
        action_hall_of_fame.setOnClickListener {
            viewModel.webViewUrl.value = "https://m.daum.net/"
            Log.d("BottomSheet", "Button 4 Clicked ${viewModel.webViewUrl.value}")

        }
        action_liked_pictures.setOnClickListener {
            viewModel.webViewUrl.value = "https://m.nate.com/"
            Log.d("BottomSheet", "Button 5 Clicked ${viewModel.webViewUrl.value}")

        }
        action_events.setOnClickListener {
            viewModel.webViewUrl.value = "https://www.danawa.com/"
            Log.d("BottomSheet", "Button 6 Clicked ${viewModel.webViewUrl.value}")

        }
        action_close_bottom_sheet.setOnClickListener {
            dismiss()
        }
    }
}

1.5. BottomSheet Layout (XML)

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="webViewModel"
            type="com.example.ui.main.webview.WebViewViewModel" />
    </data>


    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/bottomNavigationViewBackground"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="auto"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:behavior_fitToContents="true">


[7 Image/Icons as Buttons]
 Example:
            <LinearLayout
                android:id="@+id/action_my_pictures"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_weight="1"
                android:orientation="vertical"
                android:clickable="true"
                android:focusable="true">

                <ImageView
                    android:id="@+id/icon_my_pictures"
                    android:layout_width="36dp"
                    android:layout_height="36dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@drawable/ic_user_color" />

                <TextView
                    android:id="@+id/icon_my_pictures_text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:singleLine="true"
                    android:text="My Gallery"
                    android:paddingTop="6dp"
                    android:textAlignment="center"
                    android:textSize="12sp" />
        </LinearLayout>
    </LinearLayout>
</layout>

2. LOG output (for Button Clicks)

D/BottomSheet: Button 1 Clicked https://www.google.com/
D/BottomSheet: Button 2 Clicked https://www.hotmail.de/
D/BottomSheet: Button 3 Clicked https://amazon.com/
D/BottomSheet: Button 4 Clicked https://m.daum.net/
D/BottomSheet: Button 4 Clicked https://m.daum.net/
D/BottomSheet: Button 5 Clicked https://m.nate.com/
D/BottomSheet: Button 6 Clicked https://www.danawa.com/

미리 감사드립니다.


답변1

문제는 당신이 viewModel에 제공하는 삶의 범위에 있다고 생각합니다.현재 코드는 다음과 같습니다.

viewModel = ViewModelProvider(this).get(WebViewViewModel::class.java)

이 코드는 두 개의 서로 다른 프래그먼트 내에서 호출되며 ViewModelProvider가 현재 프래그먼트 인스턴스 (this)로 초기화되기 때문입니다. 뷰 모델은이 범위 (조각 범위)에서만 사용할 수 있습니다. 따라서 각 조각의 끝에서 새로운 ViewModel을 얻습니다. 조각간에 ViewModel을 공유하려면 다른 접근 방식을 사용해야합니다.

  1. 활동으로 ViewModelProvider를 인스턴스화합니다. (ViewModel은 활동 내의 모든 조각에서 공유됩니다)
  2. parentFragment로 ViewModelProvider를 인스턴스화합니다. (ViewModel은 모든 자식 조각에서 공유됩니다)

견본:

viewModel = ViewModelProvider(requireActivity()).get(WebViewViewModel::class.java)

viewModel = ViewModelProvider(parentFragment).get(WebViewViewModel::class.java)

또한 확인하십시오 :

ViewModel의 범위를 올바르게 지정하는 방법 https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders



 

 

 

 

출처 : https://stackoverflow.com/questions/62912041/loading-url-in-webview-from-button-click-in-bottomsheetdialogfragment-via-data-b

반응형

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band