Урок 105. Android 3. Fragments. Динамическая работа

Обсуждение уроков
narwork
Сообщения: 1
Зарегистрирован: 16 ноя 2014, 22:50

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение narwork » 16 ноя 2014, 23:11

Здравствуйте, хотел спросить как программно добавлять view-элемент на фрагмент так, чтобы при удалении и затем обратной загрузки фрагмента добавленный view-элемент не исчез. (Фрагмент в приложении создается один раз в начале, потом вызывается уже созданный, я не создаю каждый раз новый)
Такой код в описании фрагмент:

CheckBox chbDelete = (CheckBox)new CheckBox(getActivity());
llBox.addView(chbDelete); //llbox - linear layout во фрагменте

senkoevg
Сообщения: 2
Зарегистрирован: 21 ноя 2014, 07:07

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение senkoevg » 21 ноя 2014, 07:28

Всем привет, помогите пожалуйста найти ошибку. В активити при нажатии на кнопку один фрагмент должен заменяться на другой, но при нажатии на кнопку прога вылетает с ошибкой. Логи указывают на ошибку в onClick при выполнении команды commit().

Код: Выделить всё

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class MainActivity extends //ActionBarActivity 
									FragmentActivity {

	FragmentTransaction fTrans;
	TCFragment tc_frag;
	TICFragment tic_frag;
	Button BtnToTC;
	Button BtnToTIC;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		BtnToTC = (Button) findViewById(R.id.button_to_tc);
		BtnToTIC = (Button) findViewById(R.id.button_to_tic);
		tc_frag = new TCFragment();
		tic_frag = new TICFragment();
		fTrans = getSupportFragmentManager().beginTransaction();
		if (savedInstanceState == null) {
			fTrans.add(R.id.container, tc_frag).commit();
			BtnToTC.setEnabled(false);
			BtnToTIC.setEnabled(true);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.button_to_tc:
			fTrans.replace(R.id.container, tc_frag);
			BtnToTC.setEnabled(false);
			BtnToTIC.setEnabled(true);
			break;
		case R.id.button_to_tic:
			fTrans.replace(R.id.container, tic_frag);
			BtnToTC.setEnabled(true);
			BtnToTIC.setEnabled(false);
			fTrans.addToBackStack(null);
			break;
		}
		fTrans.commit();
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class TCFragment extends Fragment {

		public TCFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.frag_timer_calc,
					container, false);
			return rootView;
		}
	}

	public static class TICFragment extends Fragment {

		public TICFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.frag_time_interval_calc,
					container, false);
			return rootView;
		}
	}
}
Логи ошибок:

Код: Выделить всё

11-21 04:14:19.373: E/AndroidRuntime(332): FATAL EXCEPTION: main
11-21 04:14:19.373: E/AndroidRuntime(332): java.lang.IllegalStateException: Could not execute method of the activity
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.view.View$1.onClick(View.java:2144)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.view.View.performClick(View.java:2485)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.view.View$PerformClick.run(View.java:9080)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.os.Handler.handleCallback(Handler.java:587)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.os.Handler.dispatchMessage(Handler.java:92)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.os.Looper.loop(Looper.java:123)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.app.ActivityThread.main(ActivityThread.java:3683)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at java.lang.reflect.Method.invokeNative(Native Method)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at java.lang.reflect.Method.invoke(Method.java:507)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at dalvik.system.NativeStart.main(Native Method)
11-21 04:14:19.373: E/AndroidRuntime(332): Caused by: java.lang.reflect.InvocationTargetException
11-21 04:14:19.373: E/AndroidRuntime(332): 	at java.lang.reflect.Method.invokeNative(Native Method)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at java.lang.reflect.Method.invoke(Method.java:507)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.view.View$1.onClick(View.java:2139)
11-21 04:14:19.373: E/AndroidRuntime(332): 	... 11 more
11-21 04:14:19.373: E/AndroidRuntime(332): Caused by: java.lang.IllegalStateException: commit already called
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:623)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:615)
11-21 04:14:19.373: E/AndroidRuntime(332): 	at ru.senkoevg.timercalculator.MainActivity.onClick(MainActivity.java:72)
11-21 04:14:19.373: E/AndroidRuntime(332): 	... 14 more

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Mikhail_dev » 21 ноя 2014, 10:04

Вы уже выполнили транзакцию и закрыли её коммитом (fTrans.add(R.id.container, tc_frag).commit();), поэтому и ругается что вы еще раз пытаетесь сделать коммит в onClick.
P.S. не пишите так транзакции, не делайте их глобальными. Пишите прямо в методе весь код, связанный с транзакцией, не размазывайте её на весь класс.

senkoevg
Сообщения: 2
Зарегистрирован: 21 ноя 2014, 07:07

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение senkoevg » 27 ноя 2014, 07:44

Всем привет, еще раз обращаюсь за помощью. Та же программа - при нажатии на кнопку в активити происходит замена одного фрагмента на другой. После смены ориентации экрана мне надо программно определить какой из двух фрагментов отображается (или оба), но ни один из методов не работает (всегда false): fragment.isAdded(), fragment.isVisible(), fragment.isResumed(), fragment.isInLayout(). Помогите плиз найти ошибку.

Код: Выделить всё

package ru.senkoevg.timercalculator;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends // ActionBarActivity
		FragmentActivity {

	final String LOG_TAG = "myLogs";

	private FragmentTransaction fTrans;
	private Fragment tc_frag;
	private Fragment tic_frag;
	Button BtnToTC;
	Button BtnToTIC;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		tc_frag = new TCFragment();
		tic_frag = new TICFragment();
		BtnToTC = (Button) findViewById(R.id.button_to_tc);
		BtnToTIC = (Button) findViewById(R.id.button_to_tic);
		boolean ScrnConfLL = ((getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) && isLarge());

		if (savedInstanceState == null) {
			fTrans = getSupportFragmentManager().beginTransaction();
			fTrans.add(R.id.container, tc_frag);
			if (ScrnConfLL == true) { //если landscape & large
				fTrans.add(R.id.containerRight, tic_frag);
			} else {	
				BtnToTC.setVisibility(View.GONE);
				BtnToTIC.setVisibility(View.VISIBLE);
			}
			fTrans.commit();
		} else {
			if (ScrnConfLL & (tic_frag.isAdded() == false)) { //если (landscape & large) & tic_frag еще не добавлен
				Log.d(LOG_TAG, "add tic_frag");
				fTrans = getSupportFragmentManager().beginTransaction();
				fTrans.add(R.id.containerRight, tic_frag).commit();
			}
			if (ScrnConfLL == false) {
				Log.d(LOG_TAG, "landscape & large == false");
				if (tic_frag.isVisible()){ //Почему-то не работает
					Log.d(LOG_TAG, "tic_frag isVisible");
					BtnToTIC.setVisibility(View.GONE);
				}
				if (tc_frag.isVisible()){ //Почему-то не работает
					Log.d(LOG_TAG, "tc_frag isVisible");
					BtnToTC.setVisibility(View.GONE);
				}
				// далее экспериментирую:
				if (tc_frag.isAdded() | tic_frag.isAdded()) {
					Log.d(LOG_TAG, "fragment added");
				}
				if (tc_frag.isVisible() | tic_frag.isVisible()) {
					Log.d(LOG_TAG, "fragment is Visible");
				}
				if (tc_frag.isResumed() | tic_frag.isResumed()) {
					Log.d(LOG_TAG, "fragment is Resumed");
				}
				if (tc_frag.isInLayout() | tic_frag.isInLayout()) {
					Log.d(LOG_TAG, "fragment is In Layout");
				}
			}
		}
	}

	public void onClick(View v) {
		fTrans = getSupportFragmentManager().beginTransaction();
		switch (v.getId()) {
		case R.id.button_to_tc:
			fTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
			fTrans.replace(R.id.container, tc_frag);
			BtnToTC.setVisibility(View.GONE);
			BtnToTIC.setVisibility(View.VISIBLE);
			break;
		case R.id.button_to_tic:
			fTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
			fTrans.replace(R.id.container, tic_frag);
			BtnToTC.setVisibility(View.VISIBLE);
			BtnToTIC.setVisibility(View.GONE);
			break;
		}
		fTrans.commit();
	}

	boolean isLarge() {
		return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
	}
}
Строка №50 в лог выводится, а дальше ни один if не срабатывает и в логах тишина.

Prospekt
Сообщения: 41
Зарегистрирован: 30 май 2012, 23:06

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Prospekt » 25 дек 2014, 14:55

Есть 3 фрагмента A B C.

Нужно чтобы при возврате с фрагмента C приложение возвращалось к фрагменту A.

Пробовал так:
Из A в B

Код: Выделить всё

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment nextScreen = new FragmentB();
transaction.replace(R.id.my_frame, nextScreen);
transaction.addToBackStack(null);
transaction.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
transaction.commit();
Из B в C

Код: Выделить всё

FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment nextScreen = new FragmentC();
transaction.replace(R.id.my_frame, nextScreen);
//    transaction.addToBackStack(null);
transaction.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
transaction.commit();
Нажимаю кнопку возврата, и действительно возвращаюсь в фрагмент A. Вот только после этого стек оказывается поломаным. И переход из A в B приводит к рисованию фрагмента B поверх A. Т.е. они как бы оба одновременно на экране. В чем дело?
Если убрать комментарии, чтобы из C возвращался в B, то все работает нормально.

Такое ощущение, что возвращение производится не в том BackStack.

finberg
Сообщения: 51
Зарегистрирован: 11 мар 2013, 14:20

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение finberg » 25 дек 2014, 18:55

Мне немого не понятно, если вы хотите чтобы С->A, то вам не надо фрагмент В ложить в стек, а вы не ложите в стек фрагмент C. Поясните, почему вы С не ложите в стек, а В ложите?

Prospekt
Сообщения: 41
Зарегистрирован: 30 май 2012, 23:06

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Prospekt » 25 дек 2014, 19:10

Фрагмент В - это лист, фрагмент С - это экран редактирования элемента(который выбирается на экране B)
При этом с B возвращаться должно (по кнопке back) на первоначальный фрагмент A, и с фрагмента С должна возвращаться к фрагменту A/
Поэтому я ложу B в стек, а C заменяю B.

mcdy
Сообщения: 5
Зарегистрирован: 12 дек 2014, 22:50

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение mcdy » 27 дек 2014, 00:36

Здраствуйте. Столкнулся с тупиком.
Кратко:
Есть стартовое активити, которое сразу же на всего себя открывает фрагмент с кнопками и другими элементами. Как при нажатии на кнопки в этом фрагменте создать новый фрагмент на весь экран, передать ему переменные и самоудалиться?

буду рад узнать, как это можно сделать, пока застрял именно на этом уроке, но примера перехода из одного фрагмента в другой не нашел...
заранее спасибо

Аватара пользователя
Neustart
Сообщения: 6
Зарегистрирован: 20 фев 2015, 01:03

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Neustart » 25 фев 2015, 23:27

ОБРАЩАЮСЬ К АВТОРУ УРОКА !
Я промучился над уроком три часа. Все дело в том, что addToBackStack() нифига не работает. нажатие кнопки "Назад", выходит из приложения. Что я только не делал. Сидел изучал логи, отлавливал экспешены, все впустую.
Все дело оказалось в том, что в первых уроках, вы научили создавать в Android Studio - MainActivity. Соответственно я все время пока изучаю эти уроки так и делаю. Но уроки писались то в эклипсе, и там активи по умолчанию - Activity. Оказалось, что если наследовать MainActivity от Activity то все работает как надо. НО по умолчанию оно то наследует от ActionBarActivity !!!!!!!!!
Внесите хоть какую-то информацию об этом в урок. Я думаю я не один такой промучился пару часов над поиском решения.
Спасибо.

Аватара пользователя
klblk
Сообщения: 1097
Зарегистрирован: 18 окт 2012, 11:17
Откуда: г. Красноярск

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение klblk » 26 фев 2015, 06:21

Вероятно если в ActionBarActivity использовать Fragment'ы из support lib, то все будет нормально работать. Хотя этого я не проверял.
И исходники в уроке написаны и там наследование от Activity, а то что студия что-то как-то не так создаёт это не проблема автора уроков, т.к. вчера FragmentActivity, сегодня ActionBarActivity, а завтра еще какая-нибудь MegaUniversalActivity. Замучаешься все уроки каждый раз обновлять под каждую прихоть ide и google.
И eclipse сейчас, создавая Activity, точно также наследует от ActionBarActivity.

Аватара пользователя
TheCoder
Сообщения: 16
Зарегистрирован: 23 апр 2015, 17:23

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение TheCoder » 10 май 2015, 18:05

Всем привет. Кто может подсказать как заменить фрагмент 2 на фрагмент 1, нажав на кнопку в фрагменте 1?

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение doter.ua » 10 май 2015, 18:56

TheCoder писал(а):Всем привет. Кто может подсказать как заменить фрагмент 2 на фрагмент 1, нажав на кнопку в фрагменте 1?
http://stackoverflow.com/a/18940937
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
TheCoder
Сообщения: 16
Зарегистрирован: 23 апр 2015, 17:23

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение TheCoder » 10 май 2015, 19:20

doter.ua, спасибо, но это не то, что мне нужно. Там сказано как заменить один фрагмент на другой. Мне же нужно сделать это, нажав на кнопку в первом фрагменте.

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение doter.ua » 10 май 2015, 19:31

TheCoder писал(а):doter.ua, спасибо, но это не то, что мне нужно. Там сказано как заменить один фрагмент на другой. Мне же нужно сделать это, нажав на кнопку в первом фрагменте.
Сделай паблик метод в хост активити к которому можно обратиться из фрагмента.
http://stackoverflow.com/a/12659795
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
TheCoder
Сообщения: 16
Зарегистрирован: 23 апр 2015, 17:23

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение TheCoder » 10 май 2015, 19:57

Разобрался. Я просто в классе второго фрагмента как layout первый указал...

Bogdan
Сообщения: 2
Зарегистрирован: 25 май 2015, 08:03

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Bogdan » 25 май 2015, 08:09

Подскажите. Можно ли делать replace для одного и того же фрагмента? У меня есть две кнопки одна добавляет один фрагмент в контейнер вторая другой фрагмент в тот же контейнер. Если нажимать кнопки по очереди то фрагменты заменяются поочередно и ни каких проблем. Но если нажать одну и туже кнопку подряд то при втором нажатии контейнер очищается и больше фрагмент не добавляется при нажатии.

Bogdan
Сообщения: 2
Зарегистрирован: 25 май 2015, 08:03

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Bogdan » 25 май 2015, 16:38

Тут вот в чем проблема с виртуальным устройством от гугла глючит. Запустил под genymotion и на реальном устройстве так все работает нормально. Эво как.

K_Vladimir
Сообщения: 36
Зарегистрирован: 28 июн 2015, 03:13

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение K_Vladimir » 09 сен 2015, 09:59

Доброго дня! )
Вопрос уже обсуждался, но без конкретного решения.
Всё по уроку, но эта строка работает не во всех случаях if (chbStack.isChecked()) {fTrans.addToBackStack(null);},
при нажатии кнопки назад приложение просто закрывается.
А именно, при использовании:
1. import android.support.v4.app.FragmentActivity; // BackStack не работает
2. import android.support.v7.app.AppCompatActivity; // BackStack не работает - а он сегодня идет по умолчанию
3. import android.app.Activity; //BackStack РАБОТАЕТ
Подскажите новичку, как сделать чтоб работал при наследовании AppCompatActivity или FragmentActivity ???

И вообще, краткий ликбез (или урок) не помешал бы по поводу правильного выбора того от чего наследоваться, создавая новый проект.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение Mikhail_dev » 09 сен 2015, 10:03

Наследуйтесь от support.v7, которая содержит в себе support.v4. Покажите свой код добавления фрагмента. У меня десятки фрагментов на этой либе и всё работает.

K_Vladimir
Сообщения: 36
Зарегистрирован: 28 июн 2015, 03:13

Re: Урок 105. Android 3. Fragments. Динамическая работа

Сообщение K_Vladimir » 09 сен 2015, 10:10

Mikhail_dev писал(а):Наследуйтесь от support.v7, которая содержит в себе support.v4. Покажите свой код добавления фрагмента. У меня десятки фрагментов на этой либе и всё работает.

Спасибо за такой быстрый ответ!
Как раз при использовании import android.support.v7.app.AppCompatActivity;
приложение и закрывается вместо перехода назад.

Код: Выделить всё

package com.vladimir.kushnarev.p1051_fragmentdynamic;

//import android.support.v4.app.FragmentActivity;    // BackStack не работает
import android.support.v7.app.AppCompatActivity;     // BackStack не работает
//import android.app.Activity;                                 //BackStack работает

import android.os.Bundle;

import android.app.FragmentTransaction;
import android.view.View;
import android.widget.CheckBox;


public class MainActivity extends AppCompatActivity {                 //AppCompatActivity {

    Fragment1 frag1;
    Fragment2 frag2;
    FragmentTransaction fTrans;
    CheckBox chbStack;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    ...........

Ответить