Создавайте подпредставления Android, такие как подпредставления iOS
Я пытаюсь программно (не используя XML-файлы) создавать собственные подпредставления в Android (это то, что я называю в iOS), которые представляют собой несколько базовых представлений (метки, кнопки, текстовые поля и т. Д.), Которые объединяются в повторно используемое подпредставление. класс, чтобы я мог использовать его в моем UIViewControllers
или же Activity
в Android.
Я не знаю, какова правильная терминология в Android. Кажется, существует миллион различных терминов.
Пользовательский вид, ViewGroups, макеты, виджеты, компоненты, все, что вы хотите назвать.
В iOS это просто делается так:
CustomView.h
@interface CustomView : UIView
@property (nonatomic, strong) UILabel *message;
@property (nonatomic, strong) UIButton *button;
@end
CustomView.m
@implementation CustomView
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self initViews];
[self initConstraints];
}
return self;
}
-(void)initViews
{
self.message = [[UILabel alloc] init];
self.button = [[UIButton alloc] init];
[self addSubview:self.message];
[self addSubview:self.button];
}
-(void)initConstraints
{
id views = @{
@"message": self.message,
@"button": self.button
};
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[message]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[message][button]|" options:0 metrics:nil views:views]];
}
@end
Теперь я могу использовать этот пользовательский вид в любом ViewController (Android) Activity
) Я выбрал.
Как добиться чего-то подобного в Android?
Я искал вокруг и из того, что я собираю в Android, чтобы добавить подпредставления, я добавляю их в Layouts
:
RelativeLayout relativeLayout = new RelativeLayout(...);
TextView textView = new TextView(...);
relativeLayout.addSubview(textView);
Значит ли это, что мне нужно продлить RelativeLayout
или же ViewGroup
?
Глядя на эту страницу: http://developer.android.com/reference/android/view/ViewGroup.html
Кажется, нам нужно написать действительно сложную логику для разметки пользовательского представления, например:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
// These keep track of the space we are using on the left and right for
// views positioned there; we need member variables so we can also use
// these for layout later.
mLeftWidth = 0;
mRightWidth = 0;
// Measurement will ultimately be computing these values.
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
// Iterate through all children, measuring them and computing our dimensions
// from their size.
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
// Measure the child.
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
// Update our size information based on the layout params. Children
// that asked to be positioned on the left or right go in those gutters.
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.position == LayoutParams.POSITION_LEFT) {
mLeftWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else if (lp.position == LayoutParams.POSITION_RIGHT) {
mRightWidth += Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
} else {
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
}
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
}
}
// Total width is the maximum width of all inner children plus the gutters.
maxWidth += mLeftWidth + mRightWidth;
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
// Report our final dimensions.
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
}
Все, что я пытаюсь сделать, - это использовать несколько основных ярлыков андроида, видов, кнопок в пользовательском представлении, как в примере с iOS выше, почему это так сложно в Android?
Я надеялся на что-то простое, как это:
public class CustomView extends View
{
public RelativeLayout mainLayout;
public TextView message;
public Button button;
// default constructor
public CustomView()
{
...
initViews();
initLayouts();
addViews();
}
public initViews()
{
mainLayout = new RelativeLayout(this);
message = new TextView(this);
button = new Button(this);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
}
public addViews()
{
mainLayout.addView(message);
mainLayout.addView(button);
setContentView(mainLayout);
}
}
Извините, я искренне пытаюсь изучать и создавать базовое приложение для Android, а не пытаться разрушить образ действий Android.
Я знаю, как добавлять и размещать подпредставления внутри Activity и делал это в течение последних двух дней, но не внутри собственного View/View Group/Layout. Я не хочу, чтобы в конечном итоге создавалось одно и то же подпредставление для каждого из моих действий в приложении для Android, это просто противоречит хорошей практике кодирования, верно?:D
Просто нужно немного советов от тех, кто занимался разработкой для iOS и Android.
редактировать
Кажется, что то, что я ищу, называется Compound Control: http://developer.android.com/guide/topics/ui/custom-components.html
Я продолжу копать и, надеюсь, добьюсь результата, которого я добиваюсь: D
Просто нужно проработать этот бизнес Inflater.
3 ответа
Хорошо, я думаю, что получил, не уверен, что это лучшее решение, но он делает то, что я хочу.
Итак, что-то вроде этого:
public class CustomView extends RelativeLayout
{
private Context context;
public TextView message;
public Button button;
public CustomView(Context context)
{
super(context);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public CustomView(Context context, AttributeSet attrs)
{
super(context, attrs);
// ---------------------------------------------------------
// store context as I like to create the views inside
// initViews() method rather than in the constructor
// ---------------------------------------------------------
this.context = context;
initViews();
initLayouts();
addViews();
}
public initViews()
{
// ----------------------------------------
// note "context" refers to this.context
// that we stored above.
// ----------------------------------------
message = new TextView(context);
...
button = new Button(context);
...
}
public initLayouts()
{
// --------------------------------------------------
// use Android layout params to position subviews
// within this custom view class
// --------------------------------------------------
message.setId(View.generateViewId());
button.setId(View.generateViewId());
RelativeLayout.LayoutParams messageLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT
);
message.setLayoutParams(messageLayoutParams);
RelativeLayout.LayoutParams buttonLayoutParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
);
button.setLayoutParams(buttonLayoutParams);
}
public addViews()
{
// adding subviews to layout
addView(message);
addView(button);
}
}
Теперь я могу использовать этот пользовательский вид в любом из моих действий:
public class MainActivity extends ActionBarActivity {
// custom view instance
protected CustomView approvalView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
initViews();
}
public initViews()
{
...
approvalView = new CustomView(this);
approvalView.message.setText("1 + 1 = 2");
approvalView.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("Logger", "Math formula approved! :D");
}
});
}
}
Inflater используется, если мы создаем наш макет с использованием XML, что мне не нравится, поэтому я сгенерировал макет моего представления программно:D
Вышеупомянутый "RelativeLayout" в "extends RelativeLayout" может быть заменен на "LinearLayout" или, конечно, на другие макеты.
Разработка приложений для Android и ios - это две разные концепции, каждая из которых имеет свой собственный способ выполнения вашей задачи. Иногда сложно разработать кусок кода в Android, а иногда в IOS. Для создания вашего экрана / дизайна / графического интерфейса в Android вы можете создать XML-файл (рекомендуется) или по коду (что сложно поддерживать в XML).
Для вашего вопроса вам не нужно создавать свой собственный ViewGroup
или же RelativeLayout
или же LinearLayout
например, если вы хотите использовать RelativeLayout
в качестве родителя для вашего представления, чем с помощью XML вы можете использовать.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Text"/>
</RelativeLayout>
Если вы хотите создать свой взгляд прагматично, чем использовать
RelativeLayout parentRelativeLayout = new RelativeLayout(context);
RelativeLayout.LayoutParams parentParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
parentRelativeLayout.setLayoutParams(parentParams);
TextView childTextView = new TextView(context);
childTextView.setText("Some Text");
mRelativeLayout.addView(childTextView);
Это всего лишь пример кода, оба имеют одинаковый вывод, но с программным подходом это будет трудно по мере роста вашего взгляда.
При поиске вашего кода вы создаете настраиваемое представление (почему?) В Android, нам нужны только настраиваемые представления, если представления по умолчанию не предоставляют некоторые функциональные возможности, которые нам нужно использовать / реализовать в нашем коде. Насколько я понимаю, вы хотите использовать пользовательские представления для повторного использования. Это хороший подход, но если Android предоставляет некоторую функциональность, чем то, почему вы пытаетесь изобрести колесо снова, просто используйте разные макеты, используйте только пользовательские представления, если вы хотите что-то дополнительное.
Чтобы добавить простой ответ для общего посетителя на этот вопрос...
Вы не можете добавить подпредставления на Android View
как вы можете с iOS UIView
,
Если вам нужно добавить подпредставления в Android, используйте один из ViewGroup
подклассы (как LinearLayout
, RelativeLayout
или даже ваш собственный подкласс).
myViewGroup.addView(myView);