У меня была такая же ситуация, когда мне приходилось устанавливать размеры кнопок в зависимости от размеров экрана и плотности. Я рассчитываю размер кнопок на основе фактического пространства для приложения, которое я получаю.
Я бы предложил вам использовать LinearLAyout вместо RelativeLayout, но, поскольку у вас есть некоторый опыт, вы должны знать о различиях и простоте использования с линейными, а не с относительными макетами.
В моем XML у меня есть root LinearLayout & 2 inner LinearLayout (row1 & row2). Каждый ряд имеет 3 кнопки.
В моем onCreate я получаю более 3 из них, используя findViewById.
Используя LayoutParams, размер и плотность экрана, я вычисляю размер кнопок и размеры текста.
Алгоритм:
- Получить высоту экрана и ширину
- Вычтите отступы и поля, которые вы используете
- Высота удержания строки заголовка
- Теперь у вас есть все свободное место. Разделите его по горизонтали и вертикали, как вам нужно
- Это даст вам размер 1 кнопки
- Установить одинаковый размер для всех кнопок
- На основе ширины кнопок, высоты и плотности определить размер текста
Вы можете начать с этого, если вам понадобится помощь, я буду там. Не стейсняйся спросить.
ОБНОВЛЕНО: КОД ДОБАВЛЕН: -
Эти методы добавлены в класс с именем "Utility" и сделаны статическими для легкого доступа к методам всего проекта:
public static ScreenInfo scrnInfo = new ScreenInfo();
public static void calculateChildSize(LinearLayout root, LinearLayout.LayoutParams row1Params, LinearLayout.LayoutParams row2Params, DisplayMetrics metrics) {
int height, width;
int childWidth, childHeight;
//gets screen dimensions
height = metrics.heightPixels; //480
width = metrics.widthPixels; //320
scrnInfo.setScreenHeight(height);
scrnInfo.setScreenWidth(width);
//Log.i("MY", "Actual Screen Height = " + height + " Width = " + width);
// Get height/width after deducting Padding of all 4 sides
height = height - (root.getPaddingBottom() + root.getPaddingTop()); // 480-70
width = width - (root.getPaddingLeft() + root.getPaddingRight()); // 320-70
//Log.i(TAG, "Actual Area after Padding W = " + width + " H = " + height);
int bottomMargin = row1Params.bottomMargin; //15
bottomMargin = (row1Params.bottomMargin %2) == 0 ? row1Params.bottomMargin : row1Params.bottomMargin+1;
// Actual Height/Width of child
childWidth = (int)(width);
childHeight = (int)(height /2) - (bottomMargin/2);
childHeight -= scrnInfo.getTitleBarHeight();
scrnInfo.setRowHeight(childHeight);
row1Params.height = childHeight;
row1Params.width = childWidth;
row1Params.bottomMargin = (bottomMargin/2);
row2Params.height = childHeight;
row2Params.width = childWidth;
row2Params.topMargin = (bottomMargin/2);
scrnInfo.setChild1LayoutParams(row1Params);
scrnInfo.setChild2LayoutParams(row2Params);
calcTileWidthHeight(childWidth);
calcTileTextSize();
//android.util.Log.i(TAG, "Child W = " + childWidth + " H = " + childHeight + " Tile W = " + scrnInfo.getTileWidth() + " Tile Text Size = " + getTileTextSize());
return;
}
public static void calcTileWidthHeight(int childWidth) {
int margin = 8;
scrnInfo.setTileWidth(((childWidth/3)-margin));
}
public static void findTitleBarHeight(Window win) {
Rect rect = new Rect();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleHeight = contentViewTop - statusHeight;
scrnInfo.setTitleBarHeight(titleHeight); // SET TitleBarHeight
//Log.i(Utility.TAG, "titleHeight = " + titleHeight + " statusHeight = " + statusHeight + " contentViewTop = " + contentViewTop);
return;
}
public static void calcTileTextSize() {
// current is 11 on W = 75 => its small
int w = scrnInfo.getTileWidth();
float ts = 11f;
if (w >= 51 && w <= 70) // Port LDPI W - 54 H -98
ts = 15f;
// Screen 320 * 480 Medium dense
else if (w >= 71 && w <= 80) // Port MDPI
ts = 13f;
else if (w >= 81 && w <= 110) // Land LDPI W - 81 H - 58
ts = 15f;
else if (w >= 111 && w <= 220) // Landscape - Perfect
ts = 18f;
else if (w >= 221 && w <= 250)
ts = 20f;
setTileTextSize(ts);
}
Класс ScreenInfo содержит установщики / получатели для следующих членов:
public class ScreenInfo {
private int titleBarHeight, screenHeight, screenWidth;
private int rowHeight;
private LinearLayout.LayoutParams child1LayoutParams, child2LayoutParams;
private int _6tiles_Width; // Width of a Tile where 3 tiles on 2rows r shown
СЕЙЧАС наступает фактическая реализация в Activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.datapage);
root = (LinearLayout) findViewById(R.id.dataroot);
row1 = (LinearLayout) findViewById(R.layout.datarow1);
row2 = (LinearLayout) findViewById(R.layout.datarow2);
btn1 = (Button) findViewById(R.id.relationBtn);
btn2 = (Button) findViewById(R.id.productBtn);
btn3 = (Button) findViewById(R.id.bankBtn);
btn4 = (Button) findViewById(R.id.locationBtn);
btn5 = (Button) findViewById(R.id.curencyBtn);
btn6 = (Button) findViewById(R.id.dataReturnBtn);
root.post(new Runnable() {
public void run() {
Utility.findTitleBarHeight(getWindow());
// CALCULATE THE SIZE OF INNER LAYOUTS
//calculateChildSize();
LinearLayout.LayoutParams row1Params = (android.widget.LinearLayout.LayoutParams) row1.getLayoutParams();
LinearLayout.LayoutParams row2Params = (android.widget.LinearLayout.LayoutParams) row2.getLayoutParams();
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Utility.calculateChildSize(root, row1Params, row2Params, metrics);
row1.setLayoutParams(Utility.scrnInfo.getChild1LayoutParams());
row2.setLayoutParams(Utility.scrnInfo.getChild2LayoutParams());
RefreshComponents();
}
});
}
protected void RefreshComponents() {
// Set background of the root
root.setBackgroundColor(Utility.getBackgroundColor());
// set Gradient Colors & text color of all buttons
RefreshGradientButtons();
}
protected void RefreshGradientButtons() {
GradientDrawable btnGradient = Utility.getButtonDrawable();
int i = -1;
for(i=0; i < row1.getChildCount(); i++) {
Button btn = (Button)row1.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
for(i=0; i < row2.getChildCount(); i++) {
Button btn = (Button)row2.getChildAt(i);
btn.setBackgroundDrawable(btnGradient);
btn.setTextColor(Utility.getTextColor());
btn.setTextSize(Utility.getTileTextSize());
}
}
Всякий раз, когда экран изменяется с книжного на альбомный или наоборот ИЛИ, если во время выполнения изменяется вся плотность, вызывается onCeate каждый раз. Следовательно, этот код добавляется в onCreate (), так что расчеты и настройки могут быть выполнены на месте.
В моем приложении это работает как шарм в версиях от 1.5 до 3.2 и всех плотностях.
Вам необходимо будет соответственно изменить ваши требования. Поскольку ваш дизайн - всего 3 кнопки подряд, в то время как мой дизайн для приведенного выше кода похож на Tiles на экране. 2 ряда по 3 кнопки в каждом ряду. Я сохранил журналы, которые я добавил, так как это поможет вам отладить и выяснить ваше решение.
Это будет работать на 100%.
* Я все равно рекомендую попробовать: просто создайте новый xml и в LinearLayout в качестве родителя добавьте свой LinearLayout кнопок и посмотрите. Это работает ? Во время выполнения попробуйте в обоих режимах. В вашем LinearLayout попробуйте удалить WeightSum. По моему мнению, это требование должно быть выполнено в самом xml. *
УДАЧИ.