我有兴趣使用用户定义的相同视图数量填充屏幕/活动。每个视图都将具有完全相同的布局:几个 TextView 和几个 Button。问题是每个按钮都将控制每个 TextView 将显示的内容。
我想实现它的方式是拥有一个 XML 和一个 Java 类。然后根据用户输入的数字,用相同的视图填充屏幕(使用 for 循环)。问题是,能做到吗?如何?我是否以正确的方式考虑它?
请提供任何输入或想法的帮助,代码示例也会很棒。
当然可以。
我认为最适合您的情况,而且您可以轻松扩展,是创建一些帮助函数来处理:
1)创建一个空屏幕 2)为屏幕创建一个按钮 3)为一个屏幕创建一个文本视图,最后 4)创建一个屏幕并填充它
你必须根据你需要的子元素来为你的视图决定合适的根元素。为简单起见,我们选择 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:扩展视图在您的活动所在的同一文件夹中创建一个名为“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;
}
}
好的,所以现在要使用它,在您的 Activity 中您可以执行以下操作:
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.
可能有错误,只是在这里输入代码,但我希望它对你有帮助!
这对你最有帮助...