Android 片段复制
Posted
技术标签:
【中文标题】Android 片段复制【英文标题】:Android Fragment Duplication 【发布时间】:2011-06-30 13:26:24 【问题描述】:我正在试用 android Honeycomb 预览版中的新类,但遇到了一个小问题。我正在制作一个棒球得分应用程序,我希望左侧的按钮(操作菜单)切换右侧的“操作窗格”,我已将其设置为片段。
我希望按钮的 onClickListener() 调用片段事务以将其换出。到目前为止它可以工作,除了当应用程序加载时,它会创建默认片段,但是当我点击一个按钮时,它不是替换默认片段,而是在它旁边创建一个全新的片段。
我已经找了好几个小时了,但我看不出我做错了什么......
请记住,我是 java/android/programming 的新手,所以我可能会遗漏一些非常明显的东西。
hc_test.java(主要活动)
package com.pte.hc_test;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class hc_test extends Activity
/** Called when the activity is first created. */
/* declare class-level variables */
// private LinearLayout touchPad;
// private TextView touchCoordText;
private Button pitchButton;
private Button hitButton;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pitchButton = (Button)findViewById(R.id.actionButton1);
hitButton = (Button)findViewById(R.id.actionButton2);
pitchButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
swapFragment(actionType.PITCH_ACTION);
);
hitButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
swapFragment(actionType.HIT_ACTION);
);
private void swapFragment(int myType)
Fragment f = new actionFragment(myType);
// Execute a transaction, replacing any existing
// fragment with this one inside the frame.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.actionFragment, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- this is the parent layout of the whole screen -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_
android:background="#2F2F4F"
>
<!-- SCOREBOARD MASTER LAYOUT -->
<LinearLayout
android:orientation="horizontal"
android:layout_
android:layout_
>
<!-- team name placeholders -->
<LinearLayout
android:orientation="vertical"
android:layout_
android:layout_
android:layout_weight="0"
android:padding="5dp"
>
<TextView style="@style/inningLabel"
android:text="TEAM"
android:layout_
android:layout_
/>
<TextView style="@style/inningValue"
android:text="@string/visitor"
android:layout_
android:layout_
/>
<TextView style="@style/inningValue"
android:text="@string/home"
android:layout_
android:layout_
/>
</LinearLayout>
<!-- end team names -->
<!-- Inning table -->
<HorizontalScrollView
android:layout_
android:layout_
android:layout_weight="1"
android:fadingEdge="vertical">
<TableLayout
android:id = "@+id/innings"
android:layout_
android:layout_
android:padding="5dp"
>
<!-- inning label row -->
<!-- get these done with code?? -->
<TableRow android:layout_>
<TextView style="@style/inningLabel"
android:id="@+id/inn1_label"
android:text="1"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn2_label"
android:text="2"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn3_label"
android:text="3"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn4_label"
android:text="4"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn5_label"
android:text="5"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn6_label"
android:text="6"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn7_label"
android:text="7"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn8_label"
android:text="8"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/inn9_label"
android:text="9"
android:layout_
/>
</TableRow>
<!-- end inning labels -->
<!-- top inning row -->
<TableRow android:layout_>
<TextView style="@style/inningValue"
android:id="@+id/top1_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top2_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top3_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top4_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top5_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top6_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top7_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top8_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/top9_label"
android:text="0"
android:layout_
/>
</TableRow>
<!-- end top inning row -->
<!-- bottom inning row -->
<TableRow android:layout_>
<TextView style="@style/inningValue"
android:id="@+id/bot1_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot2_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot3_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot4_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot5_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot6_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot7_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot8_label"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/bot9_label"
android:text="0"
android:layout_
/>
</TableRow>
<!-- end bottom inning row -->
</TableLayout>
</HorizontalScrollView>
<!-- end inning table -->
<!-- Runs, Hits, Errors Count -->
<TableLayout
android:id = "@+id/RHE"
android:layout_
android:layout_
android:layout_weight="0"
android:padding="5dp">
<TableRow android:layout_>
<TextView style="@style/inningLabel"
android:id="@+id/runLabel"
android:text="R"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/hitLabel"
android:text="H"
android:layout_
/>
<TextView style="@style/inningLabel"
android:id="@+id/errorLabel"
android:text="E"
android:layout_
/>
</TableRow>
<TableRow android:layout_>
<TextView style="@style/inningValue"
android:id="@+id/visitorRuns"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/visitorHits"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/visitorErrors"
android:text="0"
android:layout_
/>
</TableRow>
<TableRow android:layout_>
<TextView style="@style/inningValue"
android:id="@+id/homeRuns"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/homeHits"
android:text="0"
android:layout_
/>
<TextView style="@style/inningValue"
android:id="@+id/homeErrors"
android:text="0"
android:layout_
/>
</TableRow>
</TableLayout>
</LinearLayout>
<!-- END OF SCOREBOARD LAYOUT -->
<!-- MAIN ACTIVITY SECTION -->
<LinearLayout
android:orientation="horizontal"
android:layout_
android:layout_>
<!-- ACTION MENU BEGIN -->
<LinearLayout
android:orientation="vertical"
android:layout_
android:layout_
android:layout_weight="1">
<Button
android:id="@+id/actionButton1"
android:text="ActionButton1"
android:layout_
android:layout_
/>
<Button
android:id="@+id/actionButton2"
android:text="ActionButton2"
android:layout_
android:layout_
/>
<Button
android:id="@+id/actionButton3"
android:text="ActionButton3"
android:layout_
android:layout_
/>
<Button
android:id="@+id/actionButton4"
android:text="ActionButton4"
android:layout_
android:layout_
/>
<Button
android:id="@+id/actionButton5"
android:text="ActionButton5"
android:layout_
android:layout_
/>
</LinearLayout>
<!-- ACTION MENU END -->
<!-- ACTION FRAME BEGIN -->
<fragment class="com.pte.hc_test.actionFragment"
android:id="@+id/actionFragment"
android:layout_
android:layout_
android:layout_weight="1" />
<!-- ACTION FRAME END -->
</LinearLayout>
<!-- MAIN ACTIVITY SECTION END -->
<!-- LIVE STATS FRAME BEGIN -->
<LinearLayout
android:orientation="horizontal"
android:layout_
android:layout_>
<!-- left live stat pane -->
<LinearLayout
android:id="@+id/left_stat_pane"
android:orientation="vertical"
android:layout_
android:layout_
android:layout_weight="1"
>
<TextView style="@style/statHeader"
android:id="@+id/left_playerName"
android:text="PITCHER NAME"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/left_stat1"
android:text="Stat1"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/left_stat2"
android:text="Stat2"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/left_stat3"
android:text="Stat3"
android:layout_
android:layout_
/>
</LinearLayout>
<!-- end left live stat pane -->
<!-- right live stat pane -->
<LinearLayout
android:id="@+id/right_stat_pane"
android:orientation="vertical"
android:layout_
android:layout_
android:layout_weight="1"
>
<TextView style="@style/statHeader"
android:id="@+id/right_playerName"
android:text="BATTER NAME"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/right_stat1"
android:text="Stat1"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/right_stat2"
android:text="Stat2"
android:layout_
android:layout_
/>
<TextView style="@style/statText"
android:id="@+id/right_stat3"
android:text="Stat3"
android:layout_
android:layout_
/>
</LinearLayout>
<!-- end right live stat pane -->
</LinearLayout>
</LinearLayout>
actionFragment.java
package com.pte.hc_test;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class actionFragment extends Fragment
// class variables
int mActivityType;
// default (null) constructor
public actionFragment()
Log.v("PTE", "null constructor");
public actionFragment(int n)
mActivityType = n;
Log.v("PTE", "explicit constructor (" + n + ")");
@Override
public void onCreate(Bundle saved)
super.onCreate(saved);
if (saved != null)
mActivityType = saved.getInt("Type");
Log.v("PTE", "FIRE: actionFragment.onCreate()");
@Override
public void onSaveInstanceState(Bundle toSave)
toSave.putInt("Type", mActivityType);
Log.v("PTE", "FIRE: actionFragment.onSaveInstanceState()");
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
Log.v("PTE", "FIRE: actionFragment.onCreateView()");
Log.v("PTE", "with mActivityType == " + mActivityType);
try
Log.v("PTE", "with onCreateView()'s container = " + container.toString());
catch (Exception e)
Log.v("PTE", "could not convert container to string. Must be null");
Log.v("PTE", e.toString());
Context c = getActivity().getApplicationContext();
LinearLayout actionPane = new LinearLayout(c);
switch (mActivityType)
case actionType.PITCH_ACTION:
Log.v("PTE", "FIRE: actionFragment.pitchPane()");
// instantiate all the required views
// parent container
TextView topLabel = new TextView(c);
TableLayout strikeZone = new TableLayout(c);
ImageView image = new ImageView(c);
// set properties for each view
actionPane.setOrientation(LinearLayout.VERTICAL);
topLabel.setText("top Label Text");
// create the strike zone table
for(int i=1; i<6; i++)
TableRow tr = new TableRow(c);
for(int j=1; j<6; j++)
TextView tv = new TextView(c);
tv.setText("C" + j + ":R" + i);
tv.setPadding(3, 3, 3, 3);
tr.addView(tv);
strikeZone.addView(tr);
image.setPadding(0, 60, 0, 30);
image.setImageResource(R.drawable.homeplate);
// add child views to parent
actionPane.addView(topLabel);
actionPane.addView(strikeZone);
actionPane.addView(image);
return actionPane;
case actionType.HIT_ACTION:
Log.v("PTE", "FIRE: actionFragment.hitPane()");
// simple layout with a text view for testing
TextView placeholder = new TextView(c);
placeholder.setText("This is a placeholder");
actionPane.addView(placeholder);
return actionPane;
default:
Log.v("PTE", "FIRE: actionFragment.defaultPane()");
// If I comment this TextView out, I achieve my intended behavior
TextView label = new TextView(c);
label.setText("This is the default pane");
actionPane.addView(label);
return actionPane;
【问题讨论】:
我不知道具体原因,但我已经设法解决了这个问题。如果我从默认片段(我使用的 TextView 占位符)中删除子视图,它会按预期工作。 我是否应该提出一个关于为什么会发生这种行为的新问题?否则,我仍然希望有人解释为什么会发生这种情况,无论是在这个线程还是另一个线程上。 【参考方案1】:您为 switch 语句设置的默认占位符文本是通过您的 LinearLayout actionPane 创建一个视图。片段从未添加到容器中。当您点击按钮时,将调用 swapFragment 方法并将片段添加到 actionPane 视图旁边的容器中。
如果您在默认情况下删除了 actionPane 的创建,您没有看到您提到的问题。如果您想在片段中显示一些默认视图或文本,以便应用程序的初始启动被按钮触发的片段替换,您可以在 hc_test onCreate 方法中将片段添加到容器中。然后,当您触发按钮时,这将被换掉。我对此进行了测试,它可以工作,可能不是最好的方法,现在凌晨 2 点,如果我写得不清楚,请见谅!如果您愿意,可以将代码发送给您或发布。
我很好奇您是否找到了帮助您使用按钮设置片段的教程?我只能找到 listFragment 示例,并且一直在努力,直到找到您的帖子。
谢谢,
【讨论】:
谢谢,查基。我也有它的工作,当我今晚回家时,我会发布代码的工作版本以及一些我发现对处理片段很有帮助的链接。【参考方案2】:我对代码进行了一些更改,它按我的预期工作。对于任何感兴趣的人,这里是工作版本的相关片段。我没有发布单个片段布局的代码,但它实际上只是我在初稿代码中所做的 xml 版本。我喜欢 onCreateView 使用的 inflater 对象的简单性,它将代码保持在最低限度,而且我可以在不更改代码的情况下更改 XML 中的布局。
actionFragment.java
package com.pte.StatCast;
// imports
public class actionFragment extends Fragment
// class variables
int mActivityType;
// default (null) constructor
public actionFragment()
public actionFragment(int n)
this.mActivityType = n;
@Override
public void onCreate(Bundle saved)
super.onCreate(saved);
if (saved != null)
mActivityType = saved.getInt("Type");
@Override
public void onSaveInstanceState(Bundle toSave)
toSave.putInt("Type", mActivityType);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
Context c = getActivity().getApplicationContext();
LinearLayout.LayoutParams p =
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1);
View actionPane = new View(c);
switch (mActivityType)
case actionType.PITCH_ACTION:
// inflate XML resource to create pitch_frag view
actionPane = inflater.inflate(R.layout.pitch_frag, null);
actionPane.setLayoutParams(p);
// set up listener for touch events
ImageView strikeZoneImg = (ImageView)actionPane.findViewById(R.id.strikeZone);
strikeZoneImg.setOnTouchListener(new OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent e)
//DO STUFF
);
return actionPane;
case actionType.HIT_ACTION:
// inflate XML resource to create hit_frag view
actionPane = inflater.inflate(R.layout.hit_frag, null);
actionPane.setLayoutParams(p);
return actionPane;
default:
LinearLayout l = new LinearLayout(c);
l.setLayoutParams(p);
return l; // return a blank linear layout as the default action
StatCast.java
package com.pte.StatCast;
// imports
public class StatCast extends Activity
/** Called when the activity is first created. */
// Declare stuff
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// database stuff here
/*
* Swap in the pitch fragment when activity first loads
*/
swapFragment(actionType.PITCH_ACTION);
private void swapFragment(int myType)
Fragment f = new actionFragment(myType);
// Execute a transaction, replacing any existing
// fragment with this one inside the frame.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.actionFragment, f);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
Log.v("PTE", "COMPLETED: swapFragment");
我仍然不完全确定为什么第一次尝试没有奏效,但这种方法在我看来更干净一些,而且它有效,所以我没有抱怨。如果您有想法或cmets,我仍然很乐意了解这些东西。谢谢!
【讨论】:
您好,我遵循了您的代码,但在两个 .java 文件中都收到有关 actiontype 的错误:“actionType 无法解析为变量”,您能帮帮我吗?以上是关于Android 片段复制的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从一个活动传递到android中的另一个活动片段? [复制]
Android课程---Android Studio使用小技巧:提取方法代码片段
在 Android 中的两个 Fragment 之间传递数据都有哪些不同的方式? [复制]