0

ユーザーが定義した数の同じビューを画面/アクティビティに取り込むことに興味があります。各ビューのレイアウトはまったく同じです: いくつかの TextView といくつかのボタンです。問題は、各ボタンが各 TextView の表示内容を制御することです。

私が考えていた実装方法は、1 つの XML と 1 つの Java クラスを持つことでした。次に、ユーザーが入力した数に応じて、同じビューを画面に表示します (for ループを使用)。問題は、それができるかどうかです。どうやって?私はそれについて正しい方法で考えていますか?

入力や考えを手伝ってください。コード例も素晴らしいでしょう。

4

2 に答える 2

1

もちろんできます。

あなたの状況で最も簡単で、さらに簡単に拡張できると思うのは、次のことを処理するいくつかのヘルパー関数を作成することです。

1) 空の画面を作成する 2) 画面のボタンを作成する 3) 画面のテキストビューを作成し、最後に 4) 画面を作成して入力する

必要な子配列に応じて、ビューの適切なルート要素を決定する必要があります。簡単にするために、LinearLayout を選択しますが、RelativeLayout または TableLayout の例は同じです。要素を追加するときに、追加のパラメーターを使用してそれらを適切に配置する必要があることだけが異なります。

空のカスタム ビューを作成する関数は、ViewGroup (「すべてのレイアウトの派生元」) を返すことに注意してください。このように、常に ViewGroups を操作し、createCustomView 内で画面レイアウト タイプを 1 回定義するだけです。そのため、画面のタイプをすぐに変更でき、残りのコードは機能します...

インスピレーションを得るためのコードを次に示します。

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... という名前を付けるだけです。

良いコーディング!!! ここに入力したばかりの上記のコードにはいくつかのエラーがあると思いますが、アイデアが得られて、ニーズに合わせて調整できることを願っています!

EDIT : v2.0 : ビューの拡張 "MyCoolScreen.java" という名前の新しい .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 に存在するため、アクティビティ コードは非常にクリーンであり、見苦しくすることなくビュー機能を拡張することもできます。

ビューが外部の世界と通信するためのインターフェイスとリスナーを作成することも一般的な方法です。たとえば、次のようにできます。

     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.

エラーが発生する可能性があります。ここにコードを入力しただけですが、お役に立てば幸いです。

于 2013-05-14T04:38:40.223 に答える
0

Androidのビューを動的に追加および削除しますか?

これはあなたに最も役立ちます...

于 2013-05-14T04:34:44.410 に答える