在main活动中创建视图。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_视图中指定了布局组件。xml
as
<?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
}
}
我的
main活动。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);
}
}
已解决当时与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++;
}
}
这就是我解决问题的方法。它应该适用于门廊和景观。
我在此呈现portrate模式和相关片段。横向模式只是重新排列dialpad_portrate.xml
的问题
// dialpad_portrate.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<EditText
android:id="@+id/dialedNumbers"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:focusable="false"
android:focusableInTouchMode="false"
android:hint="@string/dialedNumberHint"
android:inputType="text"
android:textSize="20sp" />
<ImageButton
android:id="@+id/deleteButton"
style="@style/dialpadStyle"
android:layout_weight="0.2"
android:contentDescription="@string/deleteNumbers"
android:longClickable="true"
android:src="@drawable/ic_action_ic_delete_pink" />
<ImageButton
android:id="@+id/callButton"
style="@style/dialpadStyle"
android:layout_weight="0.1"
android:contentDescription="@string/callDialedNumbers"
android:src="@drawable/ic_call_pink" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageButton
android:id="@+id/oneButton"
style="@style/dialpadStyle"
android:contentDescription="@string/one"
android:src="@drawable/ic_dialpad_1_blue" />
<ImageButton
android:id="@+id/twoButton"
style="@style/dialpadStyle"
android:contentDescription="@string/two"
android:src="@drawable/ic_dialpad_2_blue" />
<ImageButton
android:id="@+id/threeButton"
style="@style/dialpadStyle"
android:contentDescription="@string/three"
android:src="@drawable/ic_dialpad_3_blue" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageButton
android:id="@+id/fourButton"
style="@style/dialpadStyle"
android:contentDescription="@string/four"
android:src="@drawable/ic_dialpad_4_blue" />
<ImageButton
android:id="@+id/fiveButton"
style="@style/dialpadStyle"
android:contentDescription="@string/five"
android:src="@drawable/ic_dialpad_5_blue" />
<ImageButton
android:id="@+id/sixButton"
style="@style/dialpadStyle"
android:contentDescription="@string/six"
android:src="@drawable/ic_dialpad_6_blue" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageButton
android:id="@+id/sevenButton"
style="@style/dialpadStyle"
android:contentDescription="@string/seven"
android:src="@drawable/ic_dialpad_7_blue" />
<ImageButton
android:id="@+id/eightButton"
style="@style/dialpadStyle"
android:contentDescription="@string/eight"
android:src="@drawable/ic_dialpad_8_blue" />
<ImageButton
android:id="@+id/nineButton"
style="@style/dialpadStyle"
android:contentDescription="@string/nine"
android:src="@drawable/ic_dialpad_9_blue" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageButton
android:id="@+id/starButton"
style="@style/dialpadStyle"
android:contentDescription="@string/star"
android:src="@drawable/ic_dialpad_star_blue" />
<ImageButton
android:id="@+id/zeroButton"
style="@style/dialpadStyle"
android:contentDescription="@string/zero"
android:src="@drawable/ic_dialpad_0_blue" />
<ImageButton
android:id="@+id/poundButton"
style="@style/dialpadStyle"
android:contentDescription="@string/pound"
android:src="@drawable/ic_dialpad_pound_blue" />
</TableRow>
</merge>
//DialPadView.java
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.ToneGenerator;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TableLayout;
import android.widget.TableRow;
import java.util.ArrayList;
import java.util.List;
import mypackage.R;
import mypackage.Constants;
public class DialPadView extends TableLayout {
private static final int CALL_PERMISSION_CODE = 1000;
private final String TAG = getClass().getSimpleName().toUpperCase();
private LayoutInflater inflater;
private List<Integer> sounds;
private SoundPool soundPool;
private boolean soundsReady = false;
private List<ImageButton> buttons;
private boolean canReadSounds;
private EditText dialer;
String fileLocation;
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);
}
/**
* Init function that initializes everything and changes the display based on the orientation of
* the screen
* @param context The view's context
* @param attributeSet Attributesets (null in my case)
*/
private void init(final Context context, @Nullable final AttributeSet attributeSet) {
PreferenceManager.setDefaultValues(context, R.xml.app_preferences, false);
canReadSounds =
Constants.getBooleanFromPreference(Constants.READ_DEVICE_STORAGE, getContext());
fileLocation = getFileLocation(); // location of sound file
setBackgroundColor(getResources().getColor(R.color.dialpadBackground));
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
buttons = new ArrayList<>();
// check device orientation and present appropriate view
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
makeLandscape();
} else {
makePortrate();
}
soundPool = new SoundPool(12, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(final SoundPool soundPool, final int sampleId,
final int status) {
soundsReady = true;
}
});
sounds = new ArrayList<>();
if (canReadSounds) { // permission to read from user storage
loadSounds();
}
doUserInteractions(); // when a user clicks on a number, a sound is played and the color changes.
}
/**
* Inflate rows for portrate display
*/
private void makePortrate() {
try {
inflater.inflate(R.layout.dialpad_portrate, this, true);
} catch (Exception e) {
Log.d("LayoutInflationError", e.getMessage());
}
int index = 0;
while (getChildAt(index) != null) {
if (index == 0) {
TableRow actions = (TableRow) getChildAt(index);
dialer = (EditText) actions.getChildAt(0);
} else {
TableRow row = (TableRow) getChildAt(index);
for (int i = 0; i < row.getChildCount(); i++) {
ImageButton v = (ImageButton) row.getChildAt(i);
buttons.add(v);
}
}
index++;
}
}
// OTHER METHODS
/**
* Make landscape view
*/
private void makeLandscape() {}
/**
* When an image is pressed, it plays a sound and its image changes from blue to pink
*/
@SuppressLint("ClickableViewAccessibility")
private void doUserInteractions() {}
/**
* Changes the ImageButton's background, plays the corresponding sound and clears on focused
* buttons
* @param button Current button on focuss
*/
private void performActions(ImageButton button) {}
/**
* Change the image if it is on focus
* @param view ImageButton
*/
private void changeImage(final ImageButton view) {}
/**
* Restore image button if not focussed
* @param view ImageButton
*/
private void restoreImageBackground(final ImageButton view) {}
/**
* If the current button is not on pressed on entered from the keyboard, restore the image
* background
* @param button current image (pressed or entered from the keyboard)
*/
private void restoreOtherImageResources(ImageButton button) {}
/**
* Load the pre-defined sounds
**/
private void loadSounds() {}
/**
* Play a sound based on the image pressed
* @param view ImageButton pressed
*/
private void playSound(ImageButton view) {}
/**
* Play dmtf tones if user device does not have external storage
* @param view the button pressed
*/
private void playDMTF(ImageButton view) {}
本文向大家介绍Android 创建自定义视图,包括了Android 创建自定义视图的使用技巧和注意事项,需要的朋友参考一下 示例 如果需要完全自定义的视图,则需要子类View(所有Android视图的超类),并提供自定义的sizing(onMeasure(...))和drawing(onDraw(...))方法: 创建您的自定义视图框架:每个自定义视图的基本相同。在这里,我们为自定义视图创建框架,
前言:我从一个带有小键盘的旧翻盖手机搬到了S3,用它我可以很容易地键入电话银行密码或类似的东西,在我键入时用另一只手屏蔽了一只手。 如果我将手机旋转到横向模式,我最初会得到一个尺寸较小的拨号器,但一旦我输入电话(比如语音邮件),它会跳回到纵向模式和股票拨号器。从我对自定义拨号器所做的研究来看,一旦呼叫开始,它们似乎就不起作用了,所以我不太抱希望。 唯一的解决办法是根植手机并把它黑得很深吗?(显然,
模拟ios5的拨号键盘,带有拨号键,可以调用系统的电话功能进行打电话。只有在真机中才能测试打电话功能。 作者说:修改delegate后,可以自定义电话。 [Code4App.com]
我已经使用CPT插件创建了一个自定义的post类型产品,然后我创建了三个自定义分类法,用于添加新产品,比如品牌、用法和类型。 我试图实现的是有一个页面,其中列出了自定义分类法中的所有术语,单击该分类法,您将进入一个单独的术语页面,该页面列出了使用该术语标记的所有产品。最后,单击一个产品会将您带到单个产品页面。 基本上我想要这个:家- 这对我来说都是全新的和未知的。我是用分类法发现的。php为我的分
有人能帮我创建balow图像剪切搜索栏吗?我已经用自定义拇指和分段文本浏览过SeekBar,还有SeekBar拇指位置问题 但是我没有成功创建我的客户搜索栏,请帮助我
本文向大家介绍Android如何创建自定义ActionBar,包括了Android如何创建自定义ActionBar的使用技巧和注意事项,需要的朋友参考一下 当多个界面都有很多相似部分时,可以考虑创建一个功能较全的模板。而在需要时,可以通过引用模板来实现自己想要实现的功能。比如适配器 Adapter,当很多的适配器都差不多时,就可以通过打造一个通用的适配器来实现。本例中主要是如何创建自定义的 Act