প্রোগ্রামে তৈরি করা সামগ্রীর দৃশ্যের সাথে আমি কীভাবে কোনও ক্রিয়াকলাপে একটি টুকরো যোগ করব


240

আমি এমন ক্রিয়াকলাপে একটি টুকরো যোগ করতে চাই যা এর বিন্যাসটিকে প্রোগ্রামগতভাবে প্রয়োগ করে। আমি ফ্রেগমেন্ট ডকুমেন্টেশন সন্ধান করেছি কিন্তু আমার কী প্রয়োজন তা বর্ণনা করার মতো অনেকগুলি উদাহরণ নেই। কোডটি লেখার চেষ্টা করার ধরণটি এখানে রয়েছে:

public class DebugExampleTwo extends Activity {

    private ExampleTwoFragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout frame = new FrameLayout(this);
        if (savedInstanceState == null) {
            mFragment = new ExampleTwoFragment();
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(frame.getId(), mFragment).commit();
        }

        setContentView(frame);
    }
}

...

public class ExampleTwoFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container, 
                             Bundle savedInstanceState) {
        Button button = new Button(getActivity());
        button.setText("Hello There");
        return button;
    }
}

এই কোডটি সংকলন করলেও শুরুতে ক্রাশ হয়, সম্ভবত আমার FragmentTransaction.add()ভুল। এটি করার সঠিক উপায় কী?

উত্তর:


198

দেখা যাচ্ছে যে কোডটিতে একাধিক সমস্যা রয়েছে। ক্রিয়াকলাপ হিসাবে একই জাভা ফাইলের অভ্যন্তরে কোনও পাগলকে সেভাবে ঘোষণা করা যায় না তবে পাবলিক অভ্যন্তরীণ শ্রেণি হিসাবে নয়। কাঠামোটি খণ্ডটির নির্মাতা (কোনও পরামিতি ছাড়াই) সর্বজনীন এবং দৃশ্যমান হবে বলে প্রত্যাশা করে। খণ্ডটিকে একটি অভ্যন্তরীণ শ্রেণি হিসাবে ক্রিয়াকলাপে স্থানান্তর করা, বা খণ্ডের জন্য একটি নতুন জাভা ফাইল তৈরি করা এটি ঠিক করে।

দ্বিতীয় সমস্যাটি হ'ল আপনি যখন এইভাবে কোনও খণ্ড যুক্ত করছেন তখন আপনাকে অবশ্যই খণ্ডটির ধারণাগুলি সহ একটি রেফারেন্স দিতে হবে এবং সেই দৃশ্যের অবশ্যই একটি কাস্টম আইডি থাকতে হবে। ডিফল্ট আইডি ব্যবহার করে অ্যাপটি ক্রাশ হয়ে যাবে। আপডেট হওয়া কোডটি এখানে:

public class DebugExampleTwo extends Activity {

    private static final int CONTENT_VIEW_ID = 10101010;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout frame = new FrameLayout(this);
        frame.setId(CONTENT_VIEW_ID);
        setContentView(frame, new LayoutParams(
            LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

        if (savedInstanceState == null) {
            Fragment newFragment = new DebugExampleTwoFragment();
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.add(CONTENT_VIEW_ID, newFragment).commit();
        }
    }

    public static class DebugExampleTwoFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            EditText v = new EditText(getActivity());
            v.setText("Hello Fragment!");
            return v;
        }
    }
}

115
আপনি যদি কেবল খণ্ডটিকে কার্যকলাপের শীর্ষ স্তরের সামগ্রীর দর্শন হিসাবে ব্যবহার করতে চান তবে আপনি ব্যবহার করতে পারেন ft.add(android.R.id.content, newFragment)। কেবলমাত্র একটি কাস্টম লেআউট তৈরি করা এবং আইডি সেট করা প্রয়োজন যদি খণ্ডের ধারকটি ক্রিয়াকলাপের সামগ্রী না হয়।
টনি ওং

25
আইডিটিকে হার্ড কোডিংয়ের পরিবর্তে, আপনি এটি এক্সএমএলে সংজ্ঞায়িত করতে পারেন এবং এটিকে সাধারণ (R.id.myid) হিসাবে উল্লেখ করতে পারেন ।
জেসন হ্যানলি

1
আমি কীভাবে এটি করব তা জানি না তবে মনে রাখবেন যে কোনও আইডি কেবল আপনার এটির ব্যবহারের সুযোগের ক্ষেত্রে অনন্য হতে হবে।
জেসন হ্যানলি

2
আইডিটি কেবলমাত্র উপস্থিত লেআউটটির বর্তমান উত্তরাধিকারের মধ্যে তার স্তরে অনন্য হওয়া দরকার। সুতরাং এটির রৈখিক বিন্যাসে মোড়ানো বলুন, এটি কেবল লিনিয়ার বিন্যাসের মধ্যে অন্যান্য মতামতের মধ্যে অপ্রয়োজনীয় হওয়া দরকার।
শান

1
আপনি সেটআইডি (View.NO_ID) ব্যবহার করে গতিশীল কোনও আইডি তৈরি করতে পারেন এবং তারপরে এটি কী তা দেখতে getId ()।
enl8enmentnow

71

টনি ওংয়ের মন্তব্য পড়ার পরে আমি এখানে এলাম :

public class DebugExampleTwo extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addFragment(android.R.id.content,
                    new DebugExampleTwoFragment(),
                    DebugExampleTwoFragment.FRAGMENT_TAG);
    }

}

...

public abstract class BaseActivity extends Activity {

    protected void addFragment(@IdRes int containerViewId,
                               @NonNull Fragment fragment,
                               @NonNull String fragmentTag) {
        getSupportFragmentManager()
                .beginTransaction()
                .add(containerViewId, fragment, fragmentTag)
                .disallowAddToBackStack()
                .commit();
    }

    protected void replaceFragment(@IdRes int containerViewId,
                                   @NonNull Fragment fragment,
                                   @NonNull String fragmentTag,
                                   @Nullable String backStackStateName) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(containerViewId, fragment, fragmentTag)
                .addToBackStack(backStackStateName)
                .commit();
    }

}

...

public class DebugExampleTwoFragment extends Fragment {

    public static final String FRAGMENT_TAG = 
        BuildConfig.APPLICATION_ID + ".DEBUG_EXAMPLE_TWO_FRAGMENT_TAG";

    // ...

}

Kotlin

আপনি যদি কোটলিন ব্যবহার করছেন তবে গুগলের কোটলিন এক্সটেনশনগুলি কী সরবরাহ করে বা কেবল নিজের লেখা লিখেছে তা একবার দেখে নিন।


এমন করবেন না! if (savedInstanceState == null)খণ্ড তৈরির আগে পরীক্ষা করুন , বা স্ক্রিনটি ঘোরানোর পরে আপনার দুটি টুকরোগুলি বা টুকরো পুনরায় অর্ডার হবে। addএকদম পদ্ধতি ব্যবহার করবেন না ! শুধু replace। অথবা আপনার অদ্ভুত আচরণ হবে।
কুলমাইন্ড

আপনি "ব্যাকস্ট্যাকস্টেটনাম" এর মান কোথায় পাবেন? (প্রতিস্থাপন ফাংশনটি ব্যবহার করার সময়)
ভিকজিলা

@vikzilla আপনি প্রশংসনীয় ভাল উত্তর পেতে পারেন এখানে এবং ডক্স । সংক্ষেপে: backStackStateNameস্ট্রিং এমন কিছু যা আপনার দ্বারা সংজ্ঞায়িত করা হয়েছে।
জেজেডি

34
    public class Example1 extends FragmentActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
          DemoFragment fragmentDemo = (DemoFragment) 
          getSupportFragmentManager().findFragmentById(R.id.frame_container);
          //above part is to determine which fragment is in your frame_container
          setFragment(fragmentDemo);
                       (OR)
          setFragment(new TestFragment1());
        }

        // This could be moved into an abstract BaseActivity 
        // class for being re-used by several instances
        protected void setFragment(Fragment fragment) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = 
                fragmentManager.beginTransaction();
            fragmentTransaction.replace(android.R.id.content, fragment);
            fragmentTransaction.commit();
        }
    }

ক্রিয়াকলাপ বা ফ্রেমমেন্টঅ্যাক্টিভিটিতে কোনও খণ্ড যুক্ত করতে এর জন্য একটি ধারক প্রয়োজন। সেই ধারকটি একটি " Framelayout" হওয়া উচিত , যা এক্সএমএলে অন্তর্ভুক্ত করা যেতে পারে বা অন্যথায় আপনি android.R.id.contentক্রিয়াকলাপের কোনও অংশকে সরাতে বা প্রতিস্থাপন করতে " " এর মতো ডিফল্ট ধারকটি ব্যবহার করতে পারেন ।

main.xml

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 <!-- Framelayout to display Fragments -->
   <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/imagenext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_margin="16dp"
        android:src="@drawable/next" />
</RelativeLayout>

29

সমস্ত উত্তর পড়ার পরে আমি মার্জিত উপায় নিয়ে হাজির হয়েছি:

public class MyActivity extends ActionBarActivity {

 Fragment fragment ;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    FragmentManager fm = getSupportFragmentManager();
    fragment = fm.findFragmentByTag("myFragmentTag");
    if (fragment == null) {
        FragmentTransaction ft = fm.beginTransaction();
        fragment =new MyFragment();
        ft.add(android.R.id.content,fragment,"myFragmentTag");
        ft.commit();
    }

}

মূলত আপনাকে আপনার খণ্ডের ধারক হিসাবে ফ্রেমলআউট যোগ করার দরকার নেই এর পরিবর্তে আপনি অ্যান্ড্রয়েড রুট ভিউ ধারকটিতে সরাসরি খণ্ড যুক্ত করতে পারেন

গুরুত্বপূর্ণ: খোলার প্রক্রিয়া চলাকালীন খণ্ডের পরিবর্তনশীল দৃষ্টান্তের রাষ্ট্রটি হারাতে আপনার আপত্তি না থাকলে, খালি অংশটিকে এখানে দেখানো বেশিরভাগ পদ্ধতির হিসাবে ব্যবহার করবেন না ।


উত্তরের জন্য ধন্যবাদ, এটি পুরো স্ক্রিনে খণ্ড ট্যাব যুক্ত করে? তবে আপনি কীভাবে একটি ফ্রেম বিন্যাসে যুক্ত করবেন বা পেজার দেখবেন?
ফ্ল্যাঙ্কেচেন

6
public abstract class SingleFragmentActivity extends Activity {

    public static final String FRAGMENT_TAG = "single";
    private Fragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            fragment = onCreateFragment();
           getFragmentManager().beginTransaction()
                   .add(android.R.id.content, fragment, FRAGMENT_TAG)
                   .commit();
       } else {
           fragment = getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
       }
   }

   public abstract Fragment onCreateFragment();

   public Fragment getFragment() {
       return fragment;
   }

}

ব্যবহার

public class ViewCatalogItemActivity extends SingleFragmentActivity {
    @Override
    public Fragment onCreateFragment() {
        return new FragmentWorkShops();
    }

}

6

জন্য এপিআই স্তর 17 বা উচ্চতর, View.generateViewId()এই সমস্যার সমাধান হবে। ইউটিলিটি পদ্ধতিটি একটি অনন্য আইডি সরবরাহ করে যা বিল্ড টাইমে ব্যবহৃত হয় না।


3
স্ট্যাক ওভারফ্লোতে স্বাগতম! যতক্ষণ এই তাত্ত্বিক প্রশ্নের উত্তর হতে পারে, এটা বাঞ্ছনীয় হবে উত্তর অপরিহার্য অংশের এখানে অন্তর্ভুক্ত করা, এবং রেফারেন্স এর জন্য লিঙ্ক প্রদান।
সুপারবায়াসডম্যান

3

কোটলিনে প্রোগ্রামিয়ালি ক্রিয়াকলাপে টুকরো সংযুক্ত করার জন্য, আপনি নিম্নলিখিত কোডটি দেখতে পারেন:

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

            // create fragment instance
            val fragment : FragmentName = FragmentName.newInstance()

            // for passing data to fragment
            val bundle = Bundle()
            bundle.putString("data_to_be_passed", DATA)
            fragment.arguments = bundle

            // check is important to prevent activity from attaching the fragment if already its attached
            if (savedInstanceState == null) {
                supportFragmentManager
                    .beginTransaction()
                    .add(R.id.fragment_container, fragment, "fragment_name")
                    .commit()
            }
        }

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".ui.MainActivity">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

FragmentName.kt

class FragmentName : Fragment() {

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

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

        // receiving the data passed from activity here
        val data = arguments!!.getString("data_to_be_passed")
        return view
    }

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

}

আপনি যদি কোটলিনে এক্সটেনশনের সাথে পরিচিত হন তবে আপনি এই নিবন্ধটি অনুসরণ করে এই কোডটি আরও ভাল করতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.