Я изо всех сил пытался создать вид с клавиатуры
на изображении и
вид пейзажа
Представление должно быть создано таким образом, чтобы в MainActivity.java
у меня было
DialPadView myDialPad = new DialPadView(context);
setContentView(myDialPad);
Все изображения предоставлены, и когда пользователь нажимает на кнопку, это должно измениться.
у меня в res/drawable/dialpad0.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_dialpad_0_pink" android:state_pressed="true" android:state_selected="true"/>
<item android:drawable="@drawable/ic_dialpad_0_blue_dark" android:state_focused="true" />
<item android:drawable="@drawable/ic_dialpad_0_blue" />
</selector>
Я указал компоненты компоновки в res/layout/dialpad_view.xml
как
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageButton
android:id="@+id/dialpad_1"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_1"
android:background="@drawable/dialpad1" />
<ImageButton
android:id="@+id/dialpad_2"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_2"
android:background="@drawable/dialpad2" />
<ImageButton
android:id="@+id/dialpad_3"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_3"
android:background="@drawable/dialpad3" />
...
// others
...
<ImageButton
android:id="@+id/dialpad_star"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_star"
android:background="@drawable/dialpadstar" />
<ImageButton
android:id="@+id/dialpad_0"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_0"
android:background="@drawable/dialpad0" />
<ImageButton
android:id="@+id/dialpad_pound"
style="@style/dialpadStyle"
android:contentDescription="@string/dialpad_pound"
android:background="@drawable/dialpadpound" />
</merge>
, где @string/dialpadStyle
указано как (внутри res/values/styles.xml
)
<style name="dialpadStyle" parent="Widget.AppCompat.ImageButton">
<item name="android:focusableInTouchMode">true</item>
<item name="android:focusable">true</item>
<item name="android:visible">true</item>
<item name="android:height">@dimen/dialpadHeight</item> // 150dp
<item name="android:width">@dimen/dialpadWidth</item> // 150dp
</style>
Вот как DialPadView.java
выглядит
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.ImageButton;
import android.widget.TableLayout;
import java.util.ArrayList;
import java.util.List;
import mypackage.R;
public class DialPadView extends TableLayout {
private ImageButton dialpad;
public DialPadView(final Context context){
super(context);
init(context, null);
}
public DialPadView(final Context context, @Nullable final AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(final Context context, @Nullable final AttributeSet attributeSet) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
try {
inflater.inflate(R.layout.dialpad_view, this, true);
} catch (Exception e) {
Log.e("LayoutInflationError", e.getMessage());
}
List<ImageButton> buttons = new ArrayList<>();
int index = 0;
while (getChildAt(index) != null) {
ImageButton button = (ImageButton) getChildAt(index);
buttons.add(button);
index++;
}
dialpad = (ImageButton) buttons.get(11); // just for experimenting
Log.i("Buttons", "" + buttons.size()); // gives Buttons 12
}
}
Мой MainActivity.java
выглядит так
package myPackage;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import myPackage.customView.DialPadView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DialPadView dialpad = new DialPadView(this);
setContentView(dialpad);
}
}
Это дает мне
Я бы предположил, что я не реализовал свой класс DialPadView.java
хорошо или в чем проблема. Любые советы / помощь будут оценены.
После комментариев я изменил функцию init
, чтобы она выглядела так
private void init(final Context context, @Nullable final AttributeSet attributeSet) {
setStretchAllColumns(true);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
try {
inflater.inflate(R.layout.dialpad_view, this, true);
} catch (Exception e) {
Log.e("LayoutInflationError", e.getMessage());
}
List<ImageButton> buttons = new ArrayList<>();
int index = 0;
while (getChildAt(index) != null) {
ImageButton button = (ImageButton) getChildAt(index);
buttons.add(button);
index++;
}
Log.i("Buttons|=>", "" + buttons.size()); // gives Buttons|=>: 12
// attempting to add rows
for (int i = 0; i < buttons.size(); i++) {
TableRow row = new TableRow(context);
TableRow.LayoutParams lp = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT);
row.setLayoutParams(lp);
dialpad = (ImageButton) buttons.get(i); // get an image button
row.addView(dialpad, i % 3); // add ImageButton to this row
if ((i + 1) % 3 == 0) {
addView(row, i);// add the row to the TableLayout after every 3rd entry
}
}
}
В этом случае программа вылетает со следующими ошибками
05-01 16:36:06.404 3269-3269 myPackage E/AndroidRuntime: FATAL EXCEPTION: main
Process: myPackage, PID: 3269
java.lang.RuntimeException: Unable to start activity ComponentInfo{myPackage/myPackage}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
at android.view.ViewGroup.addView(ViewGroup.java:4746)
at android.view.ViewGroup.addView(ViewGroup.java:4686)
at myPackage.customView.DialPadView.init(DialPadView.java:52)
at myPackage.customView.DialPadView.(DialPadView.java:22)
at myPackage.MainActivity.onCreate(MainActivity.java:17)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Изменено на
DialPadView.java
public class DialPadView extends TableLayout {
private List<Button> buttons;
public DialPadView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
buttons = new ArrayList<>();
loadButtonImages();
removeAllViews();
loadRowsForPortrate(context);
}
/**
* Give button all desired default functionality
*
* @param button Button to style
*/
private void styleButton(final Button button) {
button.setMaxHeight((int) getResources().getDimension(R.dimen.dialpadHeight));
button.setMaxWidth((int) getResources().getDimension(R.dimen.dialpadHeight));
button.setFocusable(true);
button.setClickable(true);
button.setFocusableInTouchMode(true);
button.setScaleX(0.12f);
button.setScaleY(0.12f);
}
/**
* Load the images to the various ImageButtons
*/
private void loadButtonImages() {
for (int i = 0; i < 12; i++) {
Button button = new Button(getContext());
styleButton(button);
buttons.add(button);
}
// give each button, its background image
if (!buttons.isEmpty()) {
buttons.get(0).setBackgroundResource(R.drawable.dialpad1);
buttons.get(1).setBackgroundResource(R.drawable.dialpad2);
buttons.get(2).setBackgroundResource(R.drawable.dialpad3);
buttons.get(3).setBackgroundResource(R.drawable.dialpad4);
buttons.get(4).setBackgroundResource(R.drawable.dialpad5);
buttons.get(5).setBackgroundResource(R.drawable.dialpad6);
buttons.get(6).setBackgroundResource(R.drawable.dialpad7);
buttons.get(7).setBackgroundResource(R.drawable.dialpad8);
buttons.get(8).setBackgroundResource(R.drawable.dialpad9);
buttons.get(9).setBackgroundResource(R.drawable.dialpadstar);
buttons.get(10).setBackgroundResource(R.drawable.dialpad0);
buttons.get(11).setBackgroundResource(R.drawable.dialpadpound);
}
}
// load rows for portrate view
private void loadRowsForPortrate(Context context) {
// Define row parameters
TableRow.LayoutParams params = new TableRow.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
params.setMargins(2, 2, 2, 2);
List<TableRow> tableRows = new ArrayList<>();
// create 4 rows and give them the row parameters above
for (int rows = 0; rows < 4; rows++) {
TableRow row = new TableRow(context);
row.setLayoutParams(params);
row.setGravity(Gravity.CENTER_VERTICAL);
tableRows.add(row);
}
// first row stuff
TableRow row1 = (TableRow) tableRows.get(0);
row1.addView(buttons.get(0), 0);
row1.addView(buttons.get(1), 1);
row1.addView(buttons.get(2), 2);
// Create second row and fill it with three imageButtons
TableRow row2 = (TableRow) tableRows.get(1);
row2.addView(buttons.get(3), 0);
row2.addView(buttons.get(4), 1);
row2.addView(buttons.get(5), 2);
// third row
TableRow row3 = (TableRow) tableRows.get(2);
row3.addView(buttons.get(6), 0);
row3.addView(buttons.get(7), 1);
row3.addView(buttons.get(8), 2);
// Fourth row
TableRow row4 = (TableRow) tableRows.get(3);
row3.addView(buttons.get(9), 0);
row3.addView(buttons.get(10), 1);
row3.addView(buttons.get(11), 2);
// add all rows to table
this.addView(row1);
this.addView(row2);
this.addView(row3);
this.addView(row4);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DialPadView dialPadView = new DialPadView(this);
setContentView(dialPadView);
}
}
Но я получаю только одно изображение на экране (номер 1)
решаемые
Сделал слияние с TableRows тогда
<TableRow>
<ImageButton
android:id="@+id/oneButton"
style="@style/dialpadStyle"
android:background="@drawable/dialpad1"
android:contentDescription="@string/dialpad_1" />
<ImageButton
android:id="@+id/twoButton"
style="@style/dialpadStyle"
android:background="@drawable/dialpad2"
android:contentDescription="@string/dialpad_2" />
<ImageButton
android:id="@+id/threeButton"
style="@style/dialpadStyle"
android:background="@drawable/dialpad3"
android:contentDescription="@string/dialpad_3" />
</TableRow>
<TableRow>
//.... others
// in `DialPadView.java`
private void init(final Context context) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
try {
inflater.inflate(R.layout.dialpad_view, this, true);
} catch (Exception e) {
Log.e("InflatorError", e.getMessage());
}
int index = 0;
while (getChildAt(index) != null) {
TableRow row = (TableRow) getChildAt(index);
index++;
}
}