Android Ошибка фрагмента: для фрагмента не найдено представление 0x7f08009e (com.example.myapplication: id / preferenceFragment) для фрагмента - PullRequest
2 голосов
/ 08 марта 2020

Я пытаюсь создать меню настроек (PreferenceScreen), которое открывается, когда пользователь нажимает на элемент на панели инструментов MainActivity. Однако когда пользователь нажимает на элемент «Настройки» на панели инструментов MainActivity, появляется следующая ошибка:

   E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplication, PID: 20257
    java.lang.IllegalArgumentException: No view found for id 0x7f08009e (com.example.myapplication:id/preferenceFragment) for fragment MyPreferenceFragment{212e66e (2406d527-5781-4a6b-845c-e7ed6f2b1d9a) id=0x7f08009e}
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:875)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
        at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
        at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7045)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

Ниже приведен код в MainActivity, где я запускаю действие для PreferenceScreen:

// Launch the menus when the user clicks on one of the menu items
override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle presses on the action bar menu items
    when (item.itemId) {
        R.id.settings -> { // User pressed "Settings" button
            try {
                val settingsFragment:Fragment = MyPreferenceFragment() // Create the Settings Fragment
                val transaction:FragmentTransaction = supportFragmentManager.beginTransaction()
                transaction.replace(R.id.preferenceFragment, settingsFragment)
                transaction.addToBackStack(null)
                transaction.commit()
            }
            catch (ex:Exception) {
                println("Exception: " + ex.toString())
            }
            return true
        }
        R.id.about -> { // User pressed "About" button
            println("ABOUT BUTTON CLICKED")
            return true
        }
        R.id.share -> { // User pressed "Share" button
            println("SHARE BUTTON PRESSED")
            return true
        }
    }
    return super.onOptionsItemSelected(item)
}

Ниже приведен мой код для фрагмента (MyPreferenceFragment):

package com.example.myapplication;

import android.os.Bundle;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SeekBarPreference;
import com.example.myapplication.R;

public class MyPreferenceFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);
        final SeekBarPreference fontSizeSeekBar = (SeekBarPreference) findPreference("font_size");
    }
}

Ниже приведен мой код для фрагментации (MyPreferencesActivity.kt):

package com.example.myapplication

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity


class MyPreferencesActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_pref)
    }
}

Ниже приведен мой код для AndroidManifest.xml (где я включил действие Preference):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MyPreferencesActivity"></activity>
    </application>
</manifest>

Ниже приведен мой XML код для страницы моих предпочтений (preferences.xml):

<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <androidx.preference.SeekBarPreference
        android:key="font_size"
        android:title="Font Size"
        android:min="12"
        android:max="32"
        android:defaultValue="14" />
</androidx.preference.PreferenceScreen>

Ниже приведен код моего фрагмента, который содержит страницу настроек (activity_pref.xml):

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <fragment
        android:id="@+id/preferenceFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.myapplication.MyPreferenceFragment" />
</FrameLayout>

Мой activity_main.xml макет не включает preferences.xml или activity_pref.xml.

Примечание. Я ищу ответ, который должен позволить пользователю щелкнуть элемент на панели инструментов MainActivity и запустить экран настроек, содержащий SeekBarPreference (который можно получить за -граммно, т.е. окончательный SeekBarPreference fontSizeSeekBar = (SeekBarPreference) findPre Ference ( "FONT_SIZE");). Ответы, которые запускают фрагмент, но не могут программно получить SeekBarPreference, не будут приняты.

Ответы [ 3 ]

3 голосов
/ 10 марта 2020

У вас есть два действия: MainActivity и MyPreferencesActivity. Из опубликованного кода совершенно неясно, где и как вы запускаете последний. Вы устанавливаете Контент в MyPreferencesActivity, но заменяете фрагмент в MainActivity. Поскольку контейнер не устанавливается через setContent в MainActivity, id / preferenceFragment не может быть найден и заменен.

Сначала необходимо запустить MyPrefenceActivity, например, путем создания и запуска намерения, а затем заменить представление внутри класса MyPrefenceActivity. после того, как для контейнера было задано содержимое.

При необходимости вы также можете создать панель инструментов с меню, которое задает c для вашей MyPreferencesActivity и обрабатывает onOptionsItemSelected внутри этого действия.

Я подробно описал последний сценарий здесь: добавить панель действий для каждого фрагмента

0 голосов
/ 10 марта 2020

Вы должны использовать этот код в действии, которое содержит preferenceFragment в файле макета:

try {
                val settingsFragment:Fragment = MyPreferenceFragment() // Create the Settings Fragment
                val transaction:FragmentTransaction = supportFragmentManager.beginTransaction()
                transaction.replace(R.id.preferenceFragment, settingsFragment)
                transaction.addToBackStack(null)
                transaction.commit()
            }
            catch (ex:Exception) {
                println("Exception: " + ex.toString())
            }

Вы получаете исключение, потому что вы использовали transaction.replace(R.id.preferenceFragment, settingsFragment) в действии, которое не имеет preferenceFragment в это файл макета! Итак, вы должны начать другое действие, когда нажата кнопка R.id.settings, что действие содержит preferenceFragment в своем файле макета. Затем используйте этот код:

transaction.replace(R.id.preferenceFragment, settingsFragment)

, так что сделайте это: package com.example.myapplication

  import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity

class MyPreferencesActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_pref)
    val settingsFragment:Fragment = MyPreferenceFragment()
    getSupportFragmentManager().beginTransaction()
      .replace(R.id.preferenceFragment, settingsFragment)
      .commit()
        }
    }

и измените этот R.id.settings клик на это:

R.id.settings -> { // User pressed "Settings" button
            try {
                val settingActivityIntent = Intent(this, 
                MyPreferencesActivity::class.java)
                startActivity(settingActivityIntent)
            }
            catch (ex:Exception) {
                println("Exception: " + ex.toString())
            }
            return true
        }
0 голосов
/ 10 марта 2020

Если вы замените фрагмент транзакцией, вам необходимо указать идентификатор контейнера. Этот контейнер должен находиться в макете и станет родительским для представления фрагмента.

transaction.replace(R.id.preferenceFragment, settingsFragment)

Идентификатор preferenceFragment - это идентификатор фрагмента предпочтения в другом макете. Если вы хотите добавить MyPreferenceFragment в качестве дочернего элемента к основному действию, вам нужно предоставить идентификатор контейнера вместо preferenceFragment.

. Если вы хотите вместо этого показать MyPreferencesActivity, вам нужно только начать эту деятельность вместо транзакции фрагмента. MyPreferenceFragment автоматически добавляется с указанным макетом.

startActivity(Intent(this, MyPreferencesActivity::class.java))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...