एक लेआउट बनाकर एक कस्टम दृश्य बनाएं?


107

मैं एक कस्टम दृश्य बनाने की कोशिश कर रहा हूं जो एक निश्चित लेआउट को बदल देगा जिसका उपयोग मैं कई स्थानों पर करता हूं, लेकिन मैं ऐसा करने के लिए संघर्ष कर रहा हूं।

मूल रूप से, मैं इसे बदलना चाहता हूं:

<RelativeLayout
 android:id="@+id/dolphinLine"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
    android:layout_centerInParent="true"
 android:background="@drawable/background_box_light_blue"
 android:padding="10dip"
 android:layout_margin="10dip">
  <TextView
   android:id="@+id/dolphinTitle"
   android:layout_width="200dip"
   android:layout_height="100dip"
   android:layout_alignParentLeft="true"
   android:layout_marginLeft="10dip"
   android:text="@string/my_title"
   android:textSize="30dip"
   android:textStyle="bold"
   android:textColor="#2E4C71"
   android:gravity="center"/>
  <Button
   android:id="@+id/dolphinMinusButton"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_toRightOf="@+id/dolphinTitle"
   android:layout_marginLeft="30dip"
   android:text="@string/minus_button"
   android:textSize="70dip"
   android:textStyle="bold"
   android:gravity="center"
   android:layout_marginTop="1dip"
   android:background="@drawable/button_blue_square_selector"
   android:textColor="#FFFFFF"
   android:onClick="onClick"/>
  <TextView
   android:id="@+id/dolphinValue"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_marginLeft="15dip"
   android:background="@android:drawable/editbox_background"
   android:layout_toRightOf="@+id/dolphinMinusButton"
   android:text="0"
   android:textColor="#2E4C71"
   android:textSize="50dip"
   android:gravity="center"
   android:textStyle="bold"
   android:inputType="none"/>
  <Button
   android:id="@+id/dolphinPlusButton"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_toRightOf="@+id/dolphinValue"
   android:layout_marginLeft="15dip"
   android:text="@string/plus_button"
   android:textSize="70dip"
   android:textStyle="bold"
   android:gravity="center"
   android:layout_marginTop="1dip"
   android:background="@drawable/button_blue_square_selector"
   android:textColor="#FFFFFF"
   android:onClick="onClick"/>
</RelativeLayout>

इसके द्वारा:

<view class="com.example.MyQuantityBox"
    android:id="@+id/dolphinBox"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:myCustomAttribute="@string/my_title"/>

इसलिए, मुझे एक कस्टम लेआउट नहीं चाहिए, मैं एक कस्टम दृश्य चाहता हूं (यह इस बच्चे को देखने के लिए संभव नहीं होना चाहिए)।

केवल एक चीज जो MyQuantityBox के एक उदाहरण से दूसरे में बदल सकती है, वह है शीर्षक। मैं XML में इसे निर्दिष्ट करने में सक्षम होना चाहूंगा (जैसा कि मैं अंतिम XML लाइन पर करता हूं)

मैं यह कैसे कर सकता हूँ? क्या मुझे RelativeLayout को XML फ़ाइल में / Res / लेआउट में डालना चाहिए और इसे MyBoxQuantity वर्ग में बढ़ाना चाहिए? यदि हां, तो मैं ऐसा कैसे करूं?

धन्यवाद!


Android में "यौगिक नियंत्रण" देखें, और यह लिंक: stackoverflow.com/questions/1476371/…
greg7gkb

जवाबों:


27

हां, आप यह कर सकते हैं। RelativeLayout, LinearLayout, आदि दृश्य हैं तो एक कस्टम लेआउट एक कस्टम दृश्य है। बस कुछ विचार करने के लिए क्योंकि यदि आप एक कस्टम लेआउट बनाना चाहते थे तो आप कर सकते थे।

आप जो करना चाहते हैं, वह कंपाउंड कंट्रोल बनाएं। आप RelativeLayout का उपवर्ग बनायेंगे, हमारे सभी घटकों को कोड (TextView, आदि) में जोड़ देंगे, और अपने निर्माता में आप XML से पारित विशेषताओं को पढ़ सकते हैं। फिर आप उस विशेषता को अपने शीर्षक TextView में पास कर सकते हैं।

http://developer.android.com/guide/topics/ui/custom-components.html


130

थोड़ा पुराना है, लेकिन मैंने सोचा कि साझा करना कि मैं कैसे करूंगा, यह चब्बोन्सबब्स के जवाब के आधार पर है: मैं उपयोग करता हूं FrameLayout( दस्तावेज़ीकरण देखें) ), क्योंकि इसका उपयोग एक दृश्य को देखने के लिए किया जाता है, और इसे xml से देखने के लिए फुलाया जाता है।

निम्नलिखित कोड:

public class MyView extends FrameLayout {
    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public MyView(Context context) {
        super(context);
        initView();
    }

    private void initView() {
        inflate(getContext(), R.layout.my_view_layout, this);
    }
}

13
चूंकि देखें वर्ग स्थिर बढ़ गया है () विधि वहाँ LayoutInflater.from () के लिए कोई जरूरत नहीं है
दूरस्थ

1
क्या यह यहाँ से सिर्फ जोहान्स का समाधान नहीं है: stackoverflow.com/questions/17836695/… फिर भी, यह एक और लेआउट को भीतर ले जाता है। तो यह वास्तव में मुझे लगता है कि सबसे अच्छा समाधान नहीं है।
टोबियास रिइच

3
यह है, लेकिन जोहान्स समाधान 7.24.13 से है, और मन 7.1.13 से था ... इसके अलावा, मेरे समाधान में फ्रेमलैट का उपयोग किया गया है, जिसमें केवल एक दृश्य शामिल है (जैसा कि समाधान में संदर्भित डॉक्टर में लिखा गया है)। तो वास्तव में यह एक दृश्य के लिए एक प्लेसहोल्डर के रूप में इस्तेमाल किया जा रहा है। मैं किसी भी समाधान को नहीं जानता जो फुलाए हुए दृश्य के लिए प्लेसहोल्डर का उपयोग करके चालान नहीं करता है।
फॉक्स

मुझे नहीं मिला। वह तरीका (इनफ्लो) एक दृश्य देता है, जिसे नजरअंदाज कर दिया जाता है। लगता है कि आपको इसे वर्तमान दृश्य में जोड़ने की आवश्यकता है।
जेफरी ब्लाटमैन

1
@ जेफरी ब्लाटमैन कृपया View.inflate पद्धति की जाँच करें , हम इस एक का उपयोग करते हैं (मूल रूप में this, तीसरे पैरामीटर को निर्दिष्ट करते हुए )
V1raNi

36

यहाँ xml से फुलाकर कस्टमव्यू (कंपाउंडव्यू) बनाने का एक सरल डेमो है

attrs.xml

<resources>

    <declare-styleable name="CustomView">
        <attr format="string" name="text"/>
        <attr format="reference" name="image"/>
    </declare-styleable>
</resources>

CustomView.kt

class CustomView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
        ConstraintLayout(context, attrs, defStyleAttr) {

    init {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        View.inflate(context, R.layout.custom_layout, this)

        val ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView)
        try {
            val text = ta.getString(R.styleable.CustomView_text)
            val drawableId = ta.getResourceId(R.styleable.CustomView_image, 0)
            if (drawableId != 0) {
                val drawable = AppCompatResources.getDrawable(context, drawableId)
                image_thumb.setImageDrawable(drawable)
            }
            text_title.text = text
        } finally {
            ta.recycle()
        }
    }
}

custom_layout.xml

हमें इसका उपयोग mergeयहां करना चाहिएConstraintLayout क्योंकि इसके बजाय

यदि हम ConstraintLayoutयहां उपयोग करते हैं, तो लेआउट पदानुक्रम होगा ConstraintLayout-> ConstraintLayout-> ImageView+ TextView=> हमारे पास 1 अतिरेक ConstraintLayout=> प्रदर्शन के लिए बहुत अच्छा नहीं है

<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:parentTag="android.support.constraint.ConstraintLayout">

    <ImageView
        android:id="@+id/image_thumb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:ignore="ContentDescription"
        tools:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/text_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="@id/image_thumb"
        app:layout_constraintStart_toStartOf="@id/image_thumb"
        app:layout_constraintTop_toBottomOf="@id/image_thumb"
        tools:text="Text" />

</merge>

का उपयोग करते हुए activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <your_package.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#f00"
        app:image="@drawable/ic_android"
        app:text="Android" />

    <your_package.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0f0"
        app:image="@drawable/ic_adb"
        app:text="ADB" />

</LinearLayout>

परिणाम

यहां छवि विवरण दर्ज करें

जीथूब डेमो


4
यह या तो स्वीकार किया जाना चाहिए या इस धागे में सबसे अधिक मतदान का जवाब होना चाहिए क्योंकि इसमें अनावश्यक लेआउट पदानुक्रम का उल्लेख है।
फरीद

15

जैसा कि मैंने नीचे दिखाया है LayoutInflater का उपयोग करें।

    public View myView() {
        View v; // Creating an instance for View Object
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.myview, null);

        TextView text1 = v.findViewById(R.id.dolphinTitle);
        Button btn1 = v.findViewById(R.id.dolphinMinusButton);
        TextView text2 = v.findViewById(R.id.dolphinValue);
        Button btn2 = v.findViewById(R.id.dolphinPlusButton);

        return v;
    }

मैंने एक ही कोशिश की है। इसका काम ठीक है। लेकिन, जब मैं btn1 पर क्लिक करता हूं, तो यह वेब सेवाओं को कॉल करेगा और सर्वर से प्रतिक्रिया मिलने के बाद, मैं विशेष स्थिति text2..any मदद pls में कुछ पाठ अपडेट करना चाहता हूं?
हरिकृष्णन

7

व्यवहार में, मैंने पाया है कि आपको थोड़ा सावधान रहने की आवश्यकता है, खासकर यदि आप बार-बार थोड़ा सा xml का उपयोग कर रहे हैं। उदाहरण के लिए, मान लीजिए कि आपके पास एक तालिका है जिसे आप सूची में प्रत्येक प्रविष्टि के लिए एक तालिका पंक्ति बनाना चाहते हैं। आपने कुछ xml सेट किया है:

में my_table_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent" android:id="@+id/myTableRow">
    <ImageButton android:src="@android:drawable/ic_menu_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/rowButton"/>
    <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="TextView" android:id="@+id/rowText"></TextView>
</TableRow>

फिर आप इसे कुछ कोड के साथ प्रति पंक्ति एक बार बनाना चाहते हैं। यह मान लें कि आपने पंक्तियों को संलग्न करने के लिए एक माता-पिता TableLayout myTable को परिभाषित किया है।

for (int i=0; i<numRows; i++) {
    /*
     * 1. Make the row and attach it to myTable. For some reason this doesn't seem
     * to return the TableRow as you might expect from the xml, so you need to
     * receive the View it returns and then find the TableRow and other items, as
     * per step 2.
     */
    LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v =  inflater.inflate(R.layout.my_table_row, myTable, true);

    // 2. Get all the things that we need to refer to to alter in any way.
    TableRow    tr        = (TableRow)    v.findViewById(R.id.profileTableRow);
    ImageButton rowButton = (ImageButton) v.findViewById(R.id.rowButton);
    TextView    rowText   = (TextView)    v.findViewById(R.id.rowText);

    // 3. Configure them out as you need to
    rowText.setText("Text for this row");
    rowButton.setId(i); // So that when it is clicked we know which one has been clicked!
    rowButton.setOnClickListener(this); // See note below ...           

    /*
     * To ensure that when finding views by id on the next time round this
     * loop (or later) gie lots of spurious, unique, ids.
     */
    rowText.setId(1000+i);
    tr.setId(3000+i);
}

RowButton.setOnClickListener (यह) को संभालने पर एक स्पष्ट सरल उदाहरण के लिए, प्रोग्राम आधारित बटन के लिए Onclicklistener देखें ।


हाय नील, मैंने भी यही कोशिश की है। इसका काम ठीक है। लेकिन, जब मैं रॉबटन पर क्लिक करता हूं, तो यह वेब सेवाओं को कॉल करेगा और सर्वर से प्रतिक्रिया मिलने के बाद, मैं विशेष स्थिति में कुछ पाठ अपडेट करना चाहता हूं।
हरिकृष्णन

मेरा सवाल भी देखिए। stackoverflow.com/questions/48719970/…
हरिकृष्णन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.