我的片段有一个textview,其文本包含链接,每次单击链接时,我都会执行片段事务以添加同一片段的新实例。
为了进一步解释,我有一个托管fragmentA的ActivityA。
FragmentA从网络中提取文字。该文本包含链接。单击fragmentA中的链接时,对ActivityA的回调将启动一个新的FragmentA实例 再次获取另一个文本。
这些是我的代码:
ActivityA
public class ActivityA extends AppCompatActivity implements FragmentA.OnLinkClickedListener {
private final String TAG = "ActivityA";
Fragment mContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rock);
String rock_id = getIntent().getStringExtra("rockId");
Log.d(TAG, rock_id);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
if (savedInstanceState == null) {
Bundle bundle = new Bundle();
Fragment fragment;
fragment = new FragmentA();
bundle.putString("rock_link", rock_id);
fragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_out_right, android.R.anim.slide_in_left, android.R.anim.slide_out_right, android.R.anim.slide_in_left);
ft.add(R.id.rock_frame, fragment);
ft.commit();
}
if (savedInstanceState != null) {
mContent = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
}
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mContent != null) {
getSupportFragmentManager().putFragment(outState, "mContent", mContent);
}
}
@Override
public void OnLinkClicked(String link) {
Log.d(TAG, "The activity got the url and it is " + link);
Bundle bundle = new Bundle();
Fragment fragment;
fragment = new FragmentA();
bundle.putString("rock_link", link);
fragment.setArguments(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right, android.R.anim.slide_in_left, android.R.anim.slide_out_right);
ft.addToBackStack(null);
//ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.add(R.id.rock_frame, fragment);
ft.commit();
}
}
FragmentA
public class FragmentA extends Fragment {
OnLinkClickedListener mLinkClickedListener = sLinkCallbacks;
private AlertDialog internetDialog;
private AlertDialog sthWrongAlert;
private String url;
private String rockData;
private final String TAG = "FragmentA";
protected com.nostra13.universalimageloader.core.ImageLoader mImageLoader;
TextView rockContent;
private String rock_content;
public FragmentA() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView called");
url = getArguments().getString("rock_link");
Log.d(TAG, "Rock url is " + url);
view = inflater.inflate(R.layout.fragment_details, container, false);
showDialog();
sthWrongDialog();
rockContent = (TextView) view.findViewById(R.id.drock_content);
DisplayImageOptions defaultoptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity())
.defaultDisplayImageOptions(defaultoptions)
.writeDebugLogs()
.build();
mImageLoader = com.nostra13.universalimageloader.core.ImageLoader.getInstance();
mImageLoader.init(config);
if (savedInstanceState != null) {
rockData = savedInstanceState.getString("rockData");
if (rockData != null) {
parseHtml(rockData);
} else if (NetworkCheck.isAvailableAndConnected(getActivity())){
loadRock();
}
} else {
if (NetworkCheck.isAvailableAndConnected(getActivity())) {
//Calling method to load rocks
loadRock();
} else {
internetDialog.show();
}
}
return view;
}
public interface OnLinkClickedListener {
public void OnLinkClicked (String link);
}
private static OnLinkClickedListener sLinkCallbacks = new OnLinkClickedListener() {
@Override
public void OnLinkClicked(String link) {
}
};
private void showDialog() {
internetDialog = new AlertDialog.Builder(getActivity())
...
}
private void sthWrongDialog() {
sthWrongAlert = new AlertDialog.Builder(getActivity())
...
}
private void loadRock() {
Log.d(TAG, "loadRock called");
final ProgressBar progressBar;
progressBar = (ProgressBar) view.findViewById(R.id.progress_circle);
progressBar.setVisibility(View.VISIBLE);
Log.d(TAG, "You clicked rock id " + url);
StringRequest stringRequest = new StringRequest(url,
new Response.Listener<String>() {
// The usual codes for volley string request
//parseHtml() is called in onResponse
});
//Creating requestqueue
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
//Adding request queue
requestQueue.add(stringRequest);
}
private void parseHtml(String response) {
Log.d(TAG, "parsinghtml");
Document document = Jsoup.parse(response);
rock_content = document.select("div.entry-content").first().html();
rockContent.setVisibility(View.VISIBLE);
}
protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
{
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan clickable = new ClickableSpan() {
public void onClick(View view) {
// Do something with span.getURL() to handle the link click...
Log.e(TAG, "on click" + span.getURL());
String clickedLink = span.getURL();
mLinkClickedListener.OnLinkClicked(clickedLink);
}
};
strBuilder.setSpan(clickable, start, end, flags);
strBuilder.removeSpan(span);
}
protected void setTextViewHTML(TextView text, String html) {
CharSequence sequence = Html.fromHtml(html, new UILImageGetter(rockContent, getActivity()), null);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
for(URLSpan span : urls) {
makeLinkClickable(strBuilder, span);
}
text.setText(strBuilder);
text.setMovementMethod(LinkMovementMethod.getInstance());
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mLinkClickedListener = (OnLinkClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnLinkClickedListener");
}
}
}
FragmentA的布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:context=".ActivityA">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress_circle"
android:visibility="gone"
android:layout_centerInParent="true"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/dviewbottom"
android:hint="@string/main_body"
android:textColorLink="@color/textlink"
android:visibility="gone"
android:id="@+id/drock_content"
android:layout_margin="5dp"/>
</RelativeLayout>
</FrameLayout>
ActivityA的布局
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/scrollView"
android:fillViewport="true">
<FrameLayout
android:id="@+id/rock_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
就像我上面写的那样,当我点击FragmentA里面的rockContent中的链接时,ActivityA会启动一个新的FragmentA实例。
问题是这个新的FragmentA实例仍然具有前实例的高度。在加载数据之后,底部有一个空白区域,或者文本被截断,具体取决于前一个实例的大小。
为了进一步说明,在将数据加载到新片段之前,我可以向上和向下滚动,因为高度仍然是片段的旧实例的高度。
请问我该怎么说?即,使片段的每个新实例具有我在布局中设置的电话屏幕的高度?
修改
如果我在FragmentA布局的FrameLayout中设置android:layout_width="wrap_content"
,问题就解决了,即没有额外的空格或截断。这样做的问题是进度条不再以屏幕为中心。它位于ActionBar的正下方。