我有一个包含片段的容器的活动,这个片段还有其他片段。
现在我希望第二个或子片段访问主活动中的视图,但它返回空指针异常。
类:
public class ImageListFragment extends AbsListViewBaseFragment implements ObservableScrollViewCallbacks {
public static final int INDEX = 0;
android.support.design.widget.FloatingActionButton mFab;
@Bind(R.id.ic_call)
ImageView mIcCall;
@Bind(R.id.ic_email)
ImageView mIcEmail;
@Bind(R.id.ic_forum)
ImageView mIcForum;
FabToolbar mFabToolbar;
ObservableListView mObservableListView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_list, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
((ListView) listView).setAdapter(new ImageAdapter(getActivity()));
final SubTaB mainActivity = (SubTaB)getActivity();
ButterKnife.bind(mainActivity);
//////////////// problem here
mFabToolbar = (FabToolbar) rootView.findViewById(R.id.fabtoolbar);
////////////////
getFragmentManager().findFragmentByTag("TAG");
// rootView.findViewById(R.id.fab);
mObservableListView = (ObservableListView)rootView.findViewById(android.R.id.list);
//
mObservableListView.setAdapter(this.listView.getAdapter());
mObservableListView.setScrollViewCallbacks(this);
mainActivity.mFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mainActivity.getApplicationContext(), "msg msg", Toast.LENGTH_LONG).show();
mainActivity.mFabToolbar.expandFab();
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
@Override
public void onDestroy() {
super.onDestroy();
AnimateFirstDisplayListener.displayedImages.clear();
}
private static class ImageAdapter extends BaseAdapter {
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
private DisplayImageOptions options;
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub) // تغيير الفيو قبل تحميل الصورة
.showImageForEmptyUri(R.drawable.ic_empty) // لما الصورة فاضية
.showImageOnFail(R.drawable.ic_error) // عند الفشل
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.displayer(new CircleBitmapDisplayer(Color.WHITE, 5))
.build();
}
@Override
public int getCount() {
return IMAGE_URLS.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.item_list_image, parent, false);
holder = new ViewHolder();
holder.text = (TextView) view.findViewById(R.id.text);
holder.image = (ImageView) view.findViewById(R.id.image);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.text.setText("Item " + (position + 1));
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], holder.image, options, animateFirstListener);
return view;
}
}
static class ViewHolder {
TextView text;
ImageView image;
}
@Override
public void onScrollChanged(int i, boolean b, boolean b1) {
}
@Override
public void onDownMotionEvent() {
}
@Override
public void onUpOrCancelMotionEvent(ScrollState scrollState) {
Log.d("","Scroll scroll scroll");
if (scrollState == ScrollState.UP) {
mFabToolbar.slideOutFab();
} else if (scrollState == ScrollState.DOWN) {
mFabToolbar.slideInFab();
}
}
@OnClick(R.id.fab)
void onFabClick() {
mFabToolbar.expandFab();
}
@OnClick(R.id.call)
void onClickCall() {
iconAnim(mIcCall);
}
@OnClick(R.id.ic_email)
void onClickEmail() {
iconAnim(mIcEmail);
}
@OnClick(R.id.ic_forum)
void onClickForum() {
iconAnim(mIcForum);
}
private void iconAnim(View icon) {
Animator iconAnim = ObjectAnimator.ofPropertyValuesHolder(
icon,
PropertyValuesHolder.ofFloat("scaleX", 1f, 1.5f, 1f),
PropertyValuesHolder.ofFloat("scaleY", 1f, 1.5f, 1f));
iconAnim.start();
}
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
}
答案 0 :(得分:2)
以这种方式查找和控制视图不是一个好习惯。视图很容易与活动分离并导致意外异常。
如果需要,您应该考虑使用回调来在片段和活动之间进行通信。这样,它还可以将代码保存在正确的位置 - 因此活动是唯一触及自己视图的活动,片段也只触及自己的视图。它只是告诉活动(通过回调)活动可能想要了解的事情。它还确保碎片完全自包含,并且可以轻松重复使用。
您可以在此处阅读有关如何实施回调的信息:com.google.activity.sample
答案 1 :(得分:1)
使用EventBus
在活动和片段之间进行通信。 riggarro
建议是正确的方法。但您也可以使用EventBus
更新基本活动视图。
例如,我们需要更新片段中活动中的TextView
文本,然后按照步骤操作。
build.gradle
的{{1}}项目中。编译'de.greenrobot:eventbus:2.4.0'
app
public class UpdateTextEvent {
private String sampleTextValue;
public UpdateTextEvent(String textValue) {
this.sampleTextValue = textValue;
}
public String getTextValue() {
return sampleTextValue;
}
}
。TextView
public class TestingFragment extends Fragment{ private EventBus bus = EventBus.getDefault() public TextingFragment(){} public void onCreate(Bundle onSavedInstanceState){ super.onCreate(onSavedInstanceState); } public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){ View v = inflater.inflate(R.layout.sample_activity, parent, false); ... Button b1 = (Button) v.findViewById(R.id.button1); b1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //trigger a update to the activity bus.post(new UpdateTextEvent("testing")); } }); } }
在上面的示例中,当您从片段发布事件时,将调用public class MainActivity extends Activity{
private EventBus bus = EventBus.getDefault();
private TextView textView;
@Override
public void onCreate(Bundle onSavedInstanceState){
super.onCreate(onSavedInstanceState);
....
// The textview going to be updated on posting the event
textView = (TextView) findViewById(R.id.text1);
bus.register(this);
}
public void onEvent(UpdateTextEvent event){
textView.setText(event.getTextValue());
}
}
方法。
希望它会对你有所帮助。