공부해요/안드로이드
The specified child already has a parent. You must call removeView() on the child's parent first.
The specified child already has a parent. You must call removeView() on the child's parent first.
http://www.androidpub.com/2330392
에러 때문에 질문을 .. 또 올립니다..
ㅠㅠ..
아래 에러가 발생이 됩니다.
The specified child already has a parent. You must call removeView() on the child's parent first.
view가 등록 되어있는 상태에서 view 를 추가 해서 삽입 할 경우, 발생 된다고 하던데..
해결 방법을
전 도통 모르겠습니다..
하나 해결하면 하나 말썽이고, 도와주시면 정말 감사 하겠습니다.. ㅠㅠ
============================================
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TimePicker;
import android.widget.Toast;
/**
* Manages each alarm
*/
public class SetAlarm extends PreferenceActivity
implements TimePickerDialog.OnTimeSetListener {
private EditTextPreference mLabel;
private Preference mTimePref;
private AlarmPreference mAlarmPref;
private CheckBoxPreference mVibratePref;
private RepeatPreference mRepeatPref;
private MenuItem mDeleteAlarmItem;
private MenuItem mTestAlarmItem;
private int mId;
private boolean mEnabled;
private int mHour;
private int mMinutes;
/**
* Set an alarm. Requires an Alarms.ALARM_ID to be passed in as an
* extra. FIXME: Pass an Alarm object like every other Activity.
*/
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.alarm_prefs);
// Get each preference so we can retrieve the value later.
mLabel = (EditTextPreference) findPreference("label");
mLabel.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference p,
Object newValue) {
// Set the summary based on the new label.
p.setSummary((String) newValue);
return true;
}
});
mTimePref = findPreference("time");
mAlarmPref = (AlarmPreference) findPreference("alarm");
mVibratePref = (CheckBoxPreference) findPreference("vibrate");
mRepeatPref = (RepeatPreference) findPreference("setRepeat");
Intent i = getIntent();
mId = i.getIntExtra(Alarms.ALARM_ID, -1);
if (Log.LOGV) {
Log.v("In SetAlarm, alarm id = " + mId);
}
/* load alarm details from database */
Alarm alarm = Alarms.getAlarm(getContentResolver(), mId);
// Bad alarm, bail to avoid a NPE.
if (alarm == null) {
finish();
return;
}
mEnabled = alarm.enabled;
mLabel.setText(alarm.label);
mLabel.setSummary(alarm.label);
mHour = alarm.hour;
mMinutes = alarm.minutes;
mRepeatPref.setDaysOfWeek(alarm.daysOfWeek);
mVibratePref.setChecked(alarm.vibrate);
// Give the alert uri to the preference.
mAlarmPref.setAlert(alarm.alert);
updateTime();
// We have to do this to get the save/cancel buttons to highlight on
// their own.
getListView().setItemsCanFocus(true);
// Grab the content view so we can modify it.
FrameLayout content = (FrameLayout) getWindow().getDecorView()
.findViewById(android.R.id.content);
// Get the main ListView and remove it from the content view.
ListView lv = getListView();
content.removeView(lv);
// Create the new LinearLayout that will become the content view and
// make it vertical.
LinearLayout ll = new LinearLayout(this);
ll.removeAllViews();
ll.removeView(lv);
ll.setOrientation(LinearLayout.VERTICAL);
// Have the ListView expand to fill the screen minus the save/cancel
// buttons.
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
lp.weight = 1;
ll.addView(lv, lp);
// Inflate the buttons onto the LinearLayout.
View v = LayoutInflater.from(this).inflate(
R.layout.save_cancel_alarm, ll);
// Attach actions to each button.
Button b = (Button) v.findViewById(R.id.alarm_save);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Enable the alarm when clicking "Done"
mEnabled = true;
saveAlarm();
finish();
}
});
b = (Button) v.findViewById(R.id.alarm_cancel);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
// Replace the old content view with our new one.
setContentView(ll);
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
if (preference == mTimePref) {
new TimePickerDialog(this, this, mHour, mMinutes,
DateFormat.is24HourFormat(this)).show();
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@Override
public void onBackPressed() {
saveAlarm();
finish();
}
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
mHour = hourOfDay;
mMinutes = minute;
updateTime();
// If the time has been changed, enable the alarm.
mEnabled = true;
}
private void updateTime() {
if (Log.LOGV) {
Log.v("updateTime " + mId);
}
mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinutes,
mRepeatPref.getDaysOfWeek()));
}
private void saveAlarm() {
final String alert = mAlarmPref.getAlertString();
long time = Alarms.setAlarm(this, mId, mEnabled, mHour, mMinutes,
mRepeatPref.getDaysOfWeek(), mVibratePref.isChecked(),
mLabel.getText(), alert);
if (mEnabled) {
popAlarmSetToast(this, time);
}
}
/**
* Write alarm out to persistent store and pops toast if alarm
* enabled.
* Used only in test code.
*/
private static void saveAlarm(
Context context, int id, boolean enabled, int hour, int minute,
Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String label,
String alert, boolean popToast) {
if (Log.LOGV) Log.v("** saveAlarm " + id + " " + label + " " + enabled
+ " " + hour + " " + minute + " vibe " + vibrate);
// Fix alert string first
long time = Alarms.setAlarm(context, id, enabled, hour, minute,
daysOfWeek, vibrate, label, alert);
if (enabled && popToast) {
popAlarmSetToast(context, time);
}
}
/**
* Display a toast that tells the user how long until the alarm
* goes off. This helps prevent "am/pm" mistakes.
*/
static void popAlarmSetToast(Context context, int hour, int minute,
Alarm.DaysOfWeek daysOfWeek) {
popAlarmSetToast(context,
Alarms.calculateAlarm(hour, minute, daysOfWeek)
.getTimeInMillis());
}
private static void popAlarmSetToast(Context context, long timeInMillis) {
String toastText = formatToast(context, timeInMillis);
Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG);
ToastMaster.setToast(toast);
toast.show();
}
/**
* format "Alarm set for 2 days 7 hours and 53 minutes from
* now"
*/
static String formatToast(Context context, long timeInMillis) {
long delta = timeInMillis - System.currentTimeMillis();
long hours = delta / (1000 * 60 * 60);
long minutes = delta / (1000 * 60) % 60;
long days = hours / 24;
hours = hours % 24;
String daySeq = (days == 0) ? "" :
(days == 1) ? context.getString(R.string.day) :
context.getString(R.string.days, Long.toString(days));
String minSeq = (minutes == 0) ? "" :
(minutes == 1) ? context.getString(R.string.minute) :
context.getString(R.string.minutes, Long.toString(minutes));
String hourSeq = (hours == 0) ? "" :
(hours == 1) ? context.getString(R.string.hour) :
context.getString(R.string.hours, Long.toString(hours));
boolean dispDays = days > 0;
boolean dispHour = hours > 0;
boolean dispMinute = minutes > 0;
int index = (dispDays ? 1 : 0) |
(dispHour ? 2 : 0) |
(dispMinute ? 4 : 0);
String[] formats = context.getResources().getStringArray(R.array.alarm_set);
return String.format(formats[index], daySeq, hourSeq, minSeq);
}
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
mDeleteAlarmItem = menu.add(0, 0, 0, R.string.delete_alarm);
mDeleteAlarmItem.setIcon(android.R.drawable.ic_menu_delete);
if (AlarmClock.DEBUG) {
mTestAlarmItem = menu.add(0, 0, 0, "test alarm");
}
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
if (item == mDeleteAlarmItem) {
Alarms.deleteAlarm(this, mId);
finish();
return true;
}
if (AlarmClock.DEBUG) {
if (item == mTestAlarmItem) {
setTestAlarm();
return true;
}
}
return false;
}
/**
* Test code: this is disabled for production build. Sets
* this alarm to go off on the next minute
*/
void setTestAlarm() {
// start with now
java.util.Calendar c = java.util.Calendar.getInstance();
c.setTimeInMillis(System.currentTimeMillis());
int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY);
int nowMinute = c.get(java.util.Calendar.MINUTE);
int minutes = (nowMinute + 1) % 60;
int hour = nowHour + (nowMinute == 0 ? 1 : 0);
saveAlarm(this, mId, true, hour, minutes, mRepeatPref.getDaysOfWeek(),
true, mLabel.getText(), mAlarmPref.getAlertString(), true);
}
}
=================================
10-08 15:27:54.435: E/AndroidRuntime(24557): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.alarmclock/com.android.alarmclock.SetAlarm}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1968)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1993)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread.access$600(ActivityThread.java:127)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1159)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.os.Handler.dispatchMessage(Handler.java:99)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.os.Looper.loop(Looper.java:137)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread.main(ActivityThread.java:4507)
10-08 15:27:54.435: E/AndroidRuntime(24557): at java.lang.reflect.Method.invokeNative(Native Method)
10-08 15:27:54.435: E/AndroidRuntime(24557): at java.lang.reflect.Method.invoke(Method.java:511)
10-08 15:27:54.435: E/AndroidRuntime(24557): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
10-08 15:27:54.435: E/AndroidRuntime(24557): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
10-08 15:27:54.435: E/AndroidRuntime(24557): at dalvik.system.NativeStart.main(Native Method)
10-08 15:27:54.435: E/AndroidRuntime(24557): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.view.ViewGroup.addViewInner(ViewGroup.java:3337)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.view.ViewGroup.addView(ViewGroup.java:3208)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.view.ViewGroup.addView(ViewGroup.java:3188)
10-08 15:27:54.435: E/AndroidRuntime(24557): at com.android.alarmclock.SetAlarm.onCreate(SetAlarm.java:133)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.Activity.performCreate(Activity.java:4465)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1052)
10-08 15:27:54.435: E/AndroidRuntime(24557): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1932)
10-08 15:27:54.435: E/AndroidRuntime(24557): ... 11 more
The specified child already has a parent. You must call removeView() on the child's parent first.
이미 참조하고 있으니 예전에서 참조한 부분을 지우고 재설정 하라는 의미 입니다.
view 는 1개의 parent view 에만 add 할 수 있습니다. 중복 addView 로 인해 발생하는 문제 입니다.
com.android.alarmclock.SetAlarm.onCreate(SetAlarm.java:133) 에서 addView 하실텐데,
이미 해당 view 는 어떤 parent view 에 add 가 된상태 십니다.
해당 view 에 break point 잡으시고 그 view 의 parent view 가 뭔지 확인 하신후
그 parent view 에서 removeView 를 하셔야지 됩니다.
아래와 같이 수정하여 오류를 수정 하였습니다.
ListView lv = getListView();
((ViewGroup)lv.getParent()).removeView(lv);
'공부해요 > 안드로이드' 카테고리의 다른 글
안드로이드 스튜디오 설치하기 (0) | 2016.08.18 |
---|---|
[Andorid] Export activity – 1. 안드로이드 라이브러리 프로젝트 (0) | 2015.04.07 |
킷캣 , 갤러리 갱신 (0) | 2015.01.23 |
[ 웹앱 & 하이브리드 앱 프로그래밍 ] 한번 훑어보기 (0) | 2015.01.16 |
'공부해요/안드로이드'의 다른글
- 현재글The specified child already has a parent. You must call removeView() on the child's parent first.
You must call removeView() on the child's parent first.
반드시 removeView()를 호출 해달라네요.
부모뷰에 removeView() 혹은 removewAllView를 호출해 보세요 ㅋ