เพิ่มหลายมุมมองและคลาสแบบไดนามิกให้กับมุมมองปัจจุบัน

ฉันสนใจที่จะเติมหน้าจอ/กิจกรรมด้วยจำนวนการดูเดียวกันที่ผู้ใช้กำหนด แต่ละมุมมองจะมีเค้าโครงที่เหมือนกันทุกประการ: TextView สองอันและปุ่มสองสามปุ่ม ประเด็นก็คือแต่ละปุ่มจะควบคุมสิ่งที่แต่ละ TextView จะแสดง

วิธีที่ฉันคิดจะใช้คือมี XML หนึ่งคลาสและคลาส Java หนึ่งคลาส จากนั้นขึ้นอยู่กับจำนวนที่ผู้ใช้ป้อน เติมหน้าจอด้วยมุมมองเดียวกันจำนวนมาก (โดยใช้ for loop) คำถามคือ สามารถทำได้หรือไม่? ยังไง? ฉันคิดถูกแล้วหรือเปล่า?

โปรดช่วยแสดงความคิดเห็นหรือแสดงความคิดเห็น ตัวอย่างโค้ดก็จะดีมากเช่นกัน


person KingsInnerSoul    schedule 14.05.2013    source แหล่งที่มา
comment
ฉันยังไม่ได้ลองอะไรเลย ฉันได้อ่านวิธีที่ดีที่สุดและมีประสิทธิภาพมากที่สุดแล้ว ฉันได้เห็น Fragments, inflators และ listview แล้ว แต่ฉันต้องการให้มันตอบสนองต่อการกดปุ่มในแต่ละมุมมองที่เพิ่มแยกกัน ฉันไม่พบคำอธิบายที่เป็นเอกสารสำหรับเรื่องนั้น   -  person KingsInnerSoul    schedule 14.05.2013
comment
คุณควรลบคำถามของคุณ คุณจะถูกตั้งค่าสถานะและ downvoted เหมือนนรก   -  person Siddharth    schedule 14.05.2013
comment
นั่นเป็นอีกสิ่งหนึ่งที่ฉันกำลังมองหา จะลบคำถามได้อย่างไร?   -  person KingsInnerSoul    schedule 14.05.2013
comment
มีปุ่มลบอยู่ใต้แท็ก   -  person Siddharth    schedule 14.05.2013


คำตอบ (2)


แน่นอนมันสามารถทำได้

ฉันคิดว่าวิธีที่ง่ายที่สุดสำหรับสถานการณ์ของคุณ และคุณสามารถขยายเวลาได้อย่างง่ายดายคือการสร้างฟังก์ชันตัวช่วยบางอย่างที่ดูแล:

1) การสร้างหน้าจอว่าง 2) สร้างปุ่มสำหรับหน้าจอ 3) สร้างมุมมองข้อความสำหรับหน้าจอและสุดท้าย 4) สร้างหน้าจอและเติมข้อมูล

คุณต้องตัดสินใจเลือกองค์ประกอบรูทที่เหมาะสมสำหรับ Views ของคุณ ขึ้นอยู่กับการจัดเรียงลูกที่คุณต้องการ เพื่อความง่าย ให้เราเลือก LinearLayout แต่สำหรับ RelativeLayout หรือ TableLayout ตัวอย่างจะเหมือนกัน เพียงแต่เปลี่ยนแปลงเมื่อคุณเพิ่มองค์ประกอบ คุณจะต้องใช้พารามิเตอร์เพิ่มเติมเพื่อวางองค์ประกอบเหล่านั้นอย่างถูกต้อง

โปรดทราบว่าฟังก์ชันในการสร้างมุมมองที่กำหนดเองที่ว่างเปล่าจะส่งคืน ViewGroup ("ที่เค้าโครงทั้งหมดมาจาก") ด้วยวิธีนี้ คุณจะทำงานกับ ViewGroups ได้ตลอดเวลา และเพียงกำหนดประเภทเค้าโครงหน้าจอเพียงครั้งเดียวภายใน createCustomView ดังนั้นคุณสามารถเปลี่ยนประเภทของหน้าจอได้ที่นั่น และโค้ดที่เหลือจะทำงาน ...

นี่คือรหัสบางส่วนสำหรับแรงบันดาลใจของคุณ:

private ViewGroup createCustomView(Context context) {

    LinearLayout myCoolNewView=new LinearLayout(context); // or RelativeLayout, etc..
    return myCoolNewView;
} 

private Button createButton(Context context, String buttonText) {
    Button newButton=new Button(context);
    newButton.setText(buttonText);
    return newButton;
}

private TextView createText(Context context, String initialText) {
    TextView newText=new TextView(context);
    newText.setText(buttonText);
    return newText;
}

private ViewGroup createScreen(Context context, int numberOfButtons, int numberOfTextfields) {

    ViewGroup newScreen=createCustomView(context);
    TextView[] textViews=new TextView[numberOfTextFields];

    for (int i=0; i<numberOfTextfields; i++) {
          textViews[i]=createText(context, "hi i am text "+i);
           newScreen.addView(textViews[i]); // you ideally provide here layoutparams to properly place your buttons

    }
    for (int j=0; i<numberOfButtons; j++) {
          Button button=createButton(context, "hi i am button "+j);
          button.setOnClickListener(new OnClickListener() {
              public void onClick (View clickedView) {
                    // here you have a button keypress and you know all the textviews
                    textView[i%j].setText("hey you pressed me");
              }
          });
          newScreen.addView(button);
    }
    return newScreen;
}

ตอนนี้คุณสามารถ:

ViewGroup screen1=createScreen(context, 10, 10);
ViewGroup screen2=createScreen(context, 5, 3);
ViewGroup screen3=createScreen(context, 2, 5);

และเพิ่มหน้าจอลงในเลย์เอาต์พาเรนต์, ไปยัง ViewFlipper, ไปยัง ViewSwitcher ฯลฯ ... เช่นนี้:

 ViewGroup parentLayoutOfAllScreens=findViewById(R.id.root_of_screens);
 parentLayoutOfAllScreens.addView(screen1);
 parentLayoutOfAllScreens.addView(screen2);
 parentLayoutOfAllScreens.addView(screen3);

ใน XML คุณเพียงแค่ต้องสร้างเค้าโครงรูทและตั้งชื่อว่า root_of_screens...

การเขียนโค้ดที่ดี !!! ฉันคิดว่าอาจมีข้อผิดพลาดบางอย่างในโค้ดด้านบน เพียงพิมพ์ไว้ที่นี่ แต่ฉันหวังว่าคุณจะเข้าใจแนวคิดนี้และปรับแต่งให้เหมาะกับความต้องการของคุณ!

แก้ไข: v2.0: การขยายมุมมอง สร้าง .java ใหม่ชื่อ "MyCoolScreen.java" หรือชื่ออะไรก็ตามในโฟลเดอร์เดียวกับที่กิจกรรมของคุณอยู่ (เพื่อความเรียบง่าย):

package ........
public class MyCoolScreen extends LinearLayout {

    /** Now every view holds its own buttons, and they are private, it's good for encapsulating */
    private TextView[] mTextViews; // <-- as a convention, members should start with "m"
    private Button[] mButtons;
    private UserPressedButtons mUserPressedButtonsListener; // See below

    /** The following constructors must always be present for a custom view, and must always call super */
    public MyCoolScreen(Context context) {
        // This is the constructor you will use when creating your view programmatically
        super(context);
    }

    public MyCoolScreen(Context context, AttributeSet attrs) {

        // This is the constructor Android calls when you include your custom view in an XML
        // You can do this too!! 
        // The ATTRS will then include your numberofbuttons and numberoftextfields from the XML
        // this is beyond the example, but read about it, it's interesting

        super(context, attrs); // this MUST ALWAYS be here for custom views, or they will not work.
                               // it tells the parent view to continue the construction.
    }

    public MyCoolScreen(Context context, AttributeSet attrs, int defStyle) {
        // Another constructor Android calls from the XML
        super(context, attrs, defStyle); 
    }


    /** We create an "init" method to initialize this view from outside */
    public void init(int numberOfTextViews, int numberOfButtons) {
        createScreen(numberOfTextViews, numberOfButtons);
    }


    /** This is the same */
    private Button createButton(Context context, String buttonText) {
        Button newButton=new Button(context);
        newButton.setText(buttonText);
        return newButton;
    }

    /** This is the same */
    private TextView createText(Context context, String initialText) {
        TextView newText=new TextView(context);
        newText.setText(buttonText);
        return newText;
    }

    /** We tweak this function so it doesnt return a view, but rather fills up this one :) */

    private void createScreen(int numberOfButtons, int numberOfTextfields) {

        ViewGroup newScreen=this; // It's this view the one we gonna fill up!
        mTextViews=new TextView[numberOfTextfields];
        mButtons=new Button[numberOfButtons];
        Context context=getContext(); // Views always know their context after constructed

        for (int i=0; i<numberOfTextfields; i++) {
              mTextViews[i]=createText(context, "hi i am text "+i);
              newScreen.addView(textViews[i]); // you ideally provide here layoutparams to properly place your buttons
        }

        for (int j=0; i<numberOfButtons; j++) {
              Button button=createButton(context, "hi i am button "+j);
              button.setId(j);
              button.setOnClickListener(new OnClickListener() {
                  public void onClick (View clickedView) {
                        // here you have a button keypress and you know all the textviews
                        if (mUserPressedButtonsListener!=null) mUserPressedButtonsListener.OnButtonPressed(j);
                        textView[i%j].setText("hey you pressed me");
                  }
              });
              mButtons[j]=button;
              newScreen.addView(button);
        }
    }

    public interface UserPressedButtons {
        public void OnButtonPressed(int buttonNumber);
    }

    public void setUserPressedButtonsListener (UserPressedButtons listener) {
         mUserPressedButtonsListener=listener;
    }
}

เอาล่ะ ตอนนี้เพื่อใช้สิ่งนี้ในกิจกรรมของคุณ คุณสามารถทำได้:

    import ....... .MyCoolScreen;
    import ....... .MyCoolScreen.UserPressedButtons;

    .
    .
    .

    MyCoolScreen screen1=new MyCoolScreen(context);
    screen1.init(5,5); // initializes the screen.

    myRootLayout.addView(screen1);

สิ่งที่ยอดเยี่ยมเกี่ยวกับสิ่งนี้คือตอนนี้ฟังก์ชันการทำงานถูกรวมไว้ในมุมมองที่คุณกำหนดเองแล้ว และมันอยู่ใน .java อื่น ดังนั้นโค้ดกิจกรรมของคุณจึงสะอาดมาก และคุณยังสามารถขยายฟังก์ชัน View ได้โดยไม่ทำให้น่าเกลียดอีกด้วย

แนวทางปฏิบัติทั่วไปในการสร้างอินเทอร์เฟซและผู้ฟังสำหรับมุมมองของคุณในการสื่อสารกับโลกภายนอก ตัวอย่างเช่น เราสามารถทำได้:

     screen1.setUserPressedButtonsListener(new MyCoolScreen.UserPressedButtons() {
         @Override
         public void OnButtonPressed (int number) {
              // you know the user pressed button "number", and you can do stuff about it without
              // having to include it inside the MyCoolScreen class. Of course in your example you
              // don't need this at the moment, because the View will modify its textfield, but suppose
              // one of the buttons is "rocket launch" , that is something you will handle at the activity level, ie.

              if (number==ROCKET_LAUNCH) RocketLauncher.setTarget(10,10).launch(); // Your MyCoolScreen doesnt know how to launch rockets, but your activity maybe yes...

         }
     });

คุณสามารถทำสิ่งเจ๋งๆ ได้ทุกประเภทด้วยมุมมองแบบกำหนดเองใหม่ของคุณ ตัวอย่างเช่น คุณสามารถกำหนด:

     @Override
     public void OnDraw(Canvas c) {
          c.drawEllipse ...
          c.drawRectangle ....
     }

และคุณสามารถวาดวงกลม เส้น ฯลฯ... เหนือช่องข้อความและปุ่มของคุณ :) เพื่อให้ได้ผล คุณต้องใส่

    setWillNotDraw(false) on the constructor.

อาจมีข้อผิดพลาด เพียงพิมพ์รหัสที่นี่ แต่ฉันหวังว่าจะช่วยคุณได้!

person rupps    schedule 14.05.2013
comment
ฉันยังไม่ได้ทดสอบรหัสนี้ แต่ดูเหมือนว่าถูกต้อง เช่นเดียวกับสิ่งที่ฉันคิดจะทำ สิ่งที่ฉันขาดหายไป และโพสต์ของคุณระบุว่าแนวคิดในการแก้ปัญหาคือเกี่ยวกับการสร้าง ID ที่ไม่ซ้ำกันสำหรับแต่ละองค์ประกอบที่สร้างขึ้น ฉันจะเพิ่มรหัสของคุณ .setId(i); สำหรับแต่ละองค์ประกอบที่เพิ่ม :-) มันสายแล้ว และฉันจะทดสอบพรุ่งนี้และจะตอบกลับ -ไชโย - person KingsInnerSoul; 14.05.2013
comment
noprob :) แต่ตอนนี้คุณรู้เกี่ยวกับ setId แล้ว ฉันจะเล่าให้คุณฟังเกี่ยวกับ setTag() มันเป็นลูกพี่ลูกน้องที่มีอายุมากกว่า ด้วยวิธีนี้คุณสามารถกำหนดอะไรก็ได้ให้กับปุ่ม ไม่ใช่แค่รหัสเท่านั้น คุณสามารถทำได้: view.setTag(my button) หรือ view.setTag(new String[]{button1,screen2}) หรือกระทั่ง view.setTag(new MyStuffInfo(a,b,c,d,e))) ... และต่อมาก็ทำ view.getTag() เพื่อรับมัน :) - person rupps; 14.05.2013
comment
มันใช้งานได้อย่างมีเสน่ห์ (หลังจากแก้ไขโค้ดของคุณอย่างหนักเพื่อให้เหมาะกับแนวโน้มที่ฉันต้องการ) ตอนนี้ฉันมีปัญหากับรหัสและแท็ก และลำดับขององค์ประกอบภายใน LinearLayout ไม่พบวิธีที่ถูกต้องในการเรียก TextViews กลับคืนมาในปุ่ม onClick เพื่อดู - person KingsInnerSoul; 15.05.2013
comment
สำหรับปัญหานั้น คุณสามารถเก็บช่องข้อความทั้งหมดในอาร์เรย์ไว้ที่ระดับหน้าจอได้ เช่น จากนั้นกำหนดให้เป็น ID ปุ่มหรือแท็กดัชนีอาร์เรย์ของช่องข้อความ ใน OnClick คุณจะได้รับมุมมองที่ถูกคลิกเป็นพารามิเตอร์ ดังนั้นรหัสปุ่มจะเป็นดัชนีฟิลด์ข้อความ อย่างไรก็ตาม วิธีระดับมืออาชีพคือการสร้างคลาสหน้าจอที่ขยาย LinearLayout โดยมีตรรกะในการเติมเข้าไปภายใน และการอ้างอิงไปยังช่องข้อความและปุ่มของตัวเอง ด้วยวิธีนี้แต่ละหน้าจอจะแยกออกจากกัน และปัญหาที่คุณกำลังเผชิญอยู่จะแก้ไขได้ง่ายกว่ามาก บอกฉันว่าคุณต้องการตัวอย่างโค้ดเกี่ยวกับเรื่องนี้... - person rupps; 15.05.2013
comment
ถ้าฉันไม่เข้าใจวิธีแบบมือโปรของคุณ นั่นเป็นวิธีที่ฉันต้องการทำตั้งแต่แรก แต่ไม่รู้ว่าต้องทำอย่างไร เนื่องจาก MainScreen โฮสต์มุมมองทั้งหมด - ซึ่งเหมือนกัน - ฉันจึงคิดที่จะทำซ้ำมุมมองเดียวกันหลาย ๆ ครั้งตามที่ผู้ใช้กำหนด นั่นคือจุดที่ฉันชนกำแพงและวิธีแก้ปัญหาของคุณก็มีประโยชน์ ตัวอย่างโค้ดจะดีมากถ้าคุณทำได้ - person KingsInnerSoul; 15.05.2013
comment
ถ้าจะเข้าใจแบบมืออาชีพ ก็ควรเข้าใจตัวอย่างแรกก่อนหน้านี้ดีกว่า ตอนนี้คุณสามารถปรับโครงสร้างใหม่ได้อย่างถูกต้องแล้ว! ดูรหัสที่แนบมา - person rupps; 15.05.2013

เพิ่มและลบมุมมองใน Android แบบไดนามิกหรือไม่

สิ่งนี้จะช่วยคุณได้มากที่สุด...

person Ramesh J    schedule 14.05.2013
comment
ฉันเคยอ่านมันมาก่อนแล้ว ไม่ใช่สิ่งที่ฉันกำลังมองหา ฉันต้องการเพิ่มมุมมองต่างๆ แบบไดนามิก ซึ่งมาจากมุมมองเดียว และสามารถควบคุมเหตุการณ์สำหรับแต่ละมุมมองได้อย่างอิสระ เหตุการณ์ต่างๆ เช่น การเปลี่ยน TextViews และ ImageViews สำหรับแต่ละมุมมองแยกกัน - person KingsInnerSoul; 14.05.2013