Ответ 1
AttributeSet содержит список атрибутов, указанных в xml (например, layout_width, layout_height и т.д.).
Если вы передаете его как null, то вы должны явно указать высоту/ширину представления.
Другие questions говорят, что стиль не может быть установлен программно, но View
может быть инициализирован стилем, например, когда он загружается из XML.
Как инициализировать View
с определенным стилем программным способом (а не в XML)? Я попытался использовать View (контекст контекста, attributeSet attrs, int defStyle), но я не знаю, что нужно анализировать для второго аргумента. Передача null
приводит к тому, что View
не отображается
AttributeSet содержит список атрибутов, указанных в xml (например, layout_width, layout_height и т.д.).
Если вы передаете его как null, то вы должны явно указать высоту/ширину представления.
У меня такая же проблема, но пока не нашел практического способа прямого программирования стиля программно. Я хотел бы заполнить свой экран большим количеством виджетов, определенного типа, пусть говорят кнопки. Нецелесообразно определять их все в файле макета. Я хотел бы создать их программно, но я также хотел бы определить их стиль в файле стиля xml.
Решение, которое я разработал, состоит в том, чтобы определить только один из этих виджетов в файле макета, программно создать все остальные и клонировать информацию о стиле от первой к другим.
Далее следует пример.
В файле стиля определите стиль для ваших кнопок. Например:
<style name="niceButton">
<item name="android:layout_width">160dip</item>
<item name="android:layout_height">60dip</item>
<item name="android:gravity">center</item>
<item name="android:textSize">18dip</item>
<item name="android:textColor">#000000</item>
</style>
Затем класс подкласса "Button", выведя класс "NiceButton". Определите конструктор, который понадобится надувщику:
public NiceButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
Затем определите другой конструктор, целью которого является клонирование существующей кнопки:
public NiceButton(int id, NiceButton origButton) {
super(origButton.getContext());
setId(id);
setLayoutParams(origButton.getLayoutParams());
setGravity(origButton.getGravity());
setPadding(origButton.getPaddingLeft(),
origButton.getPaddingTop(),
origButton.getPaddingRight(),
origButton.getPaddingBottom());
setTextSize(TypedValue.COMPLEX_UNIT_PX, origButton.getTextSize());
setTextColor(origButton.getTextColors());
// ... also copy whatever other attributes you care about
}
В вашем файле макета укажите только первую из ваших кнопок. Предположим, например, что вы хотите поместить свои кнопки в таблицу:
<TableLayout android:id="@+id/button_table"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TableRow android:id="@+id/button_row_0">
<com.mydomain.mypackage.NiceButton
style="@style/niceButton" android:id="@+id/button_0" />
<!-- More rows/buttons created programmatically -->
</TableRow>
</TableLayout>
Обратите внимание, что используется полное имя класса виджетов; очевидно, вам придется заменить com.mydomain.mypackage на фактическое имя пакета.
В вашей деятельности вы можете определить массив, который будет содержать ссылку на все кнопки, и обычный прослушиватель, который будет вызываться при нажатии любой из кнопок:
NiceButton[] mButtonViews = new NiceButton[10];
private View.OnClickListener mNiceButtonClickListener = new View.OnClickListener() {
public void onClick(View view) {
int i = view.getId();
mButtonViews[i].setText("PRESSED!");
}
};
Обратите внимание, как идентификатор вида используется как индекс в массиве кнопок. Таким образом, вам понадобятся ваши кнопки с идентификатором от 0 до n-1.
Наконец, вот как вы можете создавать свои кнопки в методе onCreate:
// Retrieve some elements from the layout
TableLayout table = (TableLayout)findViewById(R.id.button_table);
TableRow row = (TableRow)findViewById(R.id.button_row_0);
NiceButton origButton = (NiceButton)findViewById(R.id.button_0);
// Prepare button 0
origButton.setId(0);
origButton.setText("Button 0");
origButton.setOnClickListener(mNiceButtonClickListener);
mButtonViews[0] = origButton;
// Create buttons 1 to 10
for (int i = 1; i < 10; i++) {
if (i % 2 == 0) {
row = new TableRow(this);
table.addView(row);
}
NiceButton button = new NiceButton(i, origButton);
button.setText("Button " + i);
button.setOnClickListener(mNiceButtonClickListener);
mButtonViews[i] = button;
row.addView(button);
}
Здесь, как экран появляется после нажатия нескольких кнопок:
Ну, там какой-то код, но в конце вы можете создать столько виджетов, которые хотите программно, и все еще иметь свои атрибуты, определенные как стиль.
Если вы хотите создать стиль, у вас есть 2 варианта: самый простой - просто указать все элементы в коде:
button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
Другой вариант - определить стиль в XML и применить его к представлению. В общем случае вы можете использовать ContextThemeWrapper
для этого:
ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);
Чтобы изменить атрибуты, связанные с текстом, в TextView (или его подклассах, например Button), существует специальный метод:
button.setTextAppearance(контекст, R.style.MyTextStyle);
Этот последний нельзя использовать для изменения всех атрибутов; например, для изменения прокладки необходимо использовать ContextThemeWrapper
. Но для цвета текста, размера и т.д. Вы можете использовать setTextAppearance
.