Я нашел решение. Получить ширину контейнера фрагмента, как только станет доступным. Установите новую ширину для всех ключей. Недействительные клавиши для перерисовки клавиатуры. Для отступа слева в строках 2,3 и 4 я просто добавил количество клавиш с высотой = 0 перед первым ключом каждой строки.
//Here we wait for the fragment width to be available
currentView.post(new Runnable() {
@Override
public void run() {
//Set the new width to the keys of the keyboard
fixKeyboard(mKeyboard, currentView.getWidth());
//Force redraw the keyboard
mKeyboardView.invalidateAllKeys();
}
});
//...
private void fixKeyboard(Keyboard k, int dw)
{
List<Keyboard.Key> keys = k.getKeys();
int key_width = (dw / 11) - 2; //-2 for margin-right
int row_number = 0;
int pos_y = 0;
int key_index_in_row = 0;
for (Keyboard.Key key : keys)
{
if (key.y != pos_y)
{
pos_y = key.y;
row_number++;
key_index_in_row = 0;
}
//Space key
if(row_number == 3 && key_index_in_row == 3)
{
key.width = 5 * key_width;
}
//Delete key
else if(row_number == 0 && key_index_in_row == 10)
{
key.width = key_width + 4; //Slightly larger
}
else
{
key.width = key_width;
}
key.gap = 0;
key.x = key_width * key_index_in_row;
key_index_in_row++;
}
}
С этим XML
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyWidth="8.5%p"
android:keyHeight="7%p"
android:keyEdgeFlags="left">
<Row>
<Key android:keyLabel="Q" android:keyEdgeFlags="left" />
<Key android:keyLabel="W" />
<Key android:keyLabel="E" />
<Key android:keyLabel="R" />
<Key android:keyLabel="T" />
<Key android:keyLabel="Z" />
<Key android:keyLabel="U" />
<Key android:keyLabel="I" />
<Key android:keyLabel="O" />
<Key android:keyLabel="P" />
<Key android:codes="55000" android:keyIcon="@drawable/del_keyboard" android:isRepeatable="true" android:keyWidth="15%p" android:keyEdgeFlags="right" />
</Row>
<Row>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px" android:keyEdgeFlags="left"/>
<Key android:keyLabel="A" />
<Key android:keyLabel="S" />
<Key android:keyLabel="D" />
<Key android:keyLabel="F" />
<Key android:keyLabel="G" />
<Key android:keyLabel="H" />
<Key android:keyLabel="J" />
<Key android:keyLabel="K" />
<Key android:keyLabel="L" android:keyEdgeFlags="right" />
</Row>
<Row>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyEdgeFlags="left" android:keyWidth="0px"/>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
<Key android:keyLabel="Y" />
<Key android:keyLabel="X" />
<Key android:keyLabel="C" />
<Key android:keyLabel="V" />
<Key android:keyLabel="B" />
<Key android:keyLabel="N" />
<Key android:keyLabel="M" android:keyEdgeFlags="right" />
</Row>
<Row>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px" android:keyEdgeFlags="left"/>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
<Key android:keyLabel=" " android:keyHeight="0px" android:keyWidth="0px"/>
<Key android:codes="55001" android:keyEdgeFlags="left" android:keyIcon="@drawable/white_space_keyboard" android:keyWidth="50%p" />
</Row>
В общем, возвращение ссылки совершенно нормально и происходит постоянно.
Если вы имеете в виду: [1231 Это все виды зла. Выделенный в стеке i
исчезнет, а вы ни на что не ссылаетесь. Это также зло:
int& getInt() {
int* i = new int;
return *i; // DON'T DO THIS.
}
Потому что теперь клиент должен в конечном итоге сделать странное:
int& myInt = getInt(); // note the &, we cannot lose this reference!
delete &myInt; // must delete...totally weird and evil
int oops = getInt();
delete &oops; // undefined behavior, we're wrongly deleting a copy, not the original
Обратите внимание, что ссылки на rvalue по-прежнему являются просто ссылками, поэтому все вредоносные приложения остаются неизменными.
Если вы хотите выделить что-то, что живет за пределами функции, используйте умный указатель (или вообще контейнер):
std::unique_ptr<int> getInt() {
return std::make_unique<int>(0);
}
И теперь клиент хранит умный указатель:
std::unique_ptr<int> x = getInt();
Ссылки также хороши для доступа к вещам, где вы знаете, что время жизни остается открытым на более высоком уровне, например:
struct immutableint {
immutableint(int i) : i_(i) {}
const int& get() const { return i_; }
private:
int i_;
};
Здесь мы это знаем
I столкнулся с реальной проблемой, где это было действительно зло. По сути, разработчик вернул ссылку на объект в векторе. Это было плохо !!!
Полные подробности, о которых я писал в Janurary: http://developer-resource.blogspot.com/2009/01/pros-and-cons-of-returing-references.html
Функция как lvalue (иначе говоря, возвращение неконстантных ссылок) должна быть удалена из C ++. Это ужасно не интуитивно понятно. Скотт Мейерс хотел использовать min () с таким поведением.
min(a,b) = 0; // What???
, которое на самом деле не является улучшением
setmin (a, b, 0);
. Последнее даже имеет больше смысла.
Я понимаю, что функция как lvalue важна для потоков в стиле C ++, но это Стоит отметить, что потоки в стиле C ++ ужасны. Я не единственный, кто так думает ... насколько я помню, у Александреску была большая статья о том, как сделать лучше,
«возвращать ссылку - это зло, потому что, просто [как я понимаю] это делает проще пропустить его удаление "
Не верно. Возврат ссылки не подразумевает семантику владения. То есть, только потому, что вы делаете это:
Value& v = thing->getTheValue();
... не означает, что вы теперь владеете памятью, на которую ссылается v;
Однако, это ужасный код:
int& getTheValue()
{
return *new int;
}
Если вы делаете что-то подобное, потому что «вам не нужен указатель на этот экземпляр» , тогда: 1) просто разыменуйте указатель, если вам нужен ссылка, и 2) вам в конечном итоге понадобится указатель, потому что вы должны сопоставить новое с удалением, и вам нужен указатель для вызова удаления.
Это не зло. Как и многие вещи в C ++, это хорошо, если используется правильно, но есть много подводных камней, о которых вы должны знать при использовании (например, возвращая ссылку на локальную переменную).
Есть хорошие вещи, которые могут быть достигнуты с этим ( как карта [имя] = "привет мир")
Вы должны вернуть ссылку на существующий объект, который не исчезает немедленно, и где вы не собираетесь любая передача права собственности.
Никогда не возвращайте ссылку на локальную переменную или что-то подобное, потому что на нее не будет ссылки.
Вы можете вернуть ссылку на что-то независимое от функции, которую вы не делаете. Не ожидайте, что вызывающая функция возьмет на себя ответственность за удаление. Это относится к типичной функции operator []
.
Если вы что-то создаете, вы должны вернуть либо значение, либо указатель (обычный или умный). Вы можете свободно возвращать значение, так как оно входит в переменную или выражение в вызывающей функции. Никогда не возвращайте указатель на локальную переменную, так как он исчезнет.
Нет. Нет, нет, тысячу раз нет.
То, что зло, - это ссылка на динамически размещенный объект и потеря первоначального указателя. Когда вы создаете
новый объект, вы берете на себя обязательство гарантированно удалить
.
Но взгляните, например, на operator <<
: that должен вернуть ссылку, иначе
cout << "foo" << "bar" << "bletch" << endl ;
не будет работать.
Not only is it not evil, it is sometimes essential. For example, it would be impossible to implement the [] operator of std::vector without using a reference return value.
There are two cases:
const reference --good idea, sometimes, especially for heavy objects or proxy classes, compiler optimization
non-const reference --bad idea, sometimes, breaks encapsulations
Both share same issue -- can potentially point to destroyed object...
I would recommend using smart pointers for many situations where you require to return a reference/pointer.
Also, note the following:
There is a formal rule - the C++ Standard (section 13.3.3.1.4 if you are interested) states that a temporary can only be bound to a const reference - if you try to use a non-const reference the compiler must flag this as an error.