I am using a FragmentPagerAdapter to show several tabs (associted with Fragments) of type MyFrag. Within MyFrag.onCreateView(), I programmatically inflate a couple of internal Fragments: MyInternalF1, and MyInternalF2.
What I get is a awkward display result. The external, MyFrag instances are fine - and are associated with their tabs. But the internal Fragments are embedded inside the wrong fragments... The first MyFrag does contain its own internal Frags, but the 2nd, 3rd, and so forth MyFrags either don't have any internal Frags, or host some other Frament's internal Frags. (The internal fragments work OK, they are just located on random fragments).
I am using the tabs/pager sample widget from the v13 samples:
samples/Support13Demos/src/com/example/android/supportv13/app/FragmentPagerSupport.java
Pseudo code:
Class MyFrag extends Fragment
{
public View onCreateView(LayoutInflater inflater,
ViewGroup container,Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
....
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.add(R.id.myfragContainer, new MyInternalF1, "InternalF1");
trans.add(R.id.myfragContainer, new MyInternalF2, "InternalF2");
trans.commit();
....
}
The problem is in the FragmentTransaction.add() function. It takes, as first parameter the ID of the containing view - containerViewId. You cannot directly pass a view, you must use an ID. Obviously, for inflated views, the id of the container view is THE SAME for all inflated interfaces. Since they all reside in the same activity - the transaction chooses the first view instance it finds. You cannot control it. So when MyFragment calls onCreate(), the internal Fragments may be added to views that do not belong to their parent.
This is a problem in the FragmentTransaction API: it would have been nice if it let you specify an explicit View, rather than just an ID, as the parent view. see: http://code.google.com/p/android/issues/detail?id=54051
Anyway, I have a workaround for now. You simply manually modify the container's ID in the onCreate function. Then pass the modified ID to the add() function.
See also: Programmatic Views how to set unique id's? (for generateViewId() function).
Class MyFrag extends Fragment
{
public View onCreateView(LayoutInflater inflater,
ViewGroup container,Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
....
int containerID = generateViewId();
infView.findViewById(R.id.frag_container).setId(containerID);
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.add(containerID, new MyInternalF1, "InternalF1");
trans.add(containerID, new MyInternalF2, "InternalF2");
trans.commit();
....
return infView;
}
}
Related
I want to create a listview from which we can use onclick and in which on long press a Context menu comes out. the code is
public class MainActivity extends ListActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String quizlist[]={"Normal","MCQ 2 Options","MCQ 3 options","MCQ 4 Options"};
ArrayAdapter<String> ab=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,quizlist);
setListAdapter(ab);
}
}
Thanks in advance
You can register an AdapterView.OnItemLongClickListener on the ListView. So what you need to do is find the list view:
in onCreate try
((ListView) getView).setOnItemLongKlickListener(...)
or
((ListView) findViewById(<the id of your list view>).setOnItemLongKlickListener(...)
When implementing an OnItemLongClickListener you will have to override the onItemLongClick method:
From the documentation:
public abstract boolean onItemLongClick (AdapterView<?> parent, View view, int position, long id)
Added in API level 1 Callback method to be invoked when an item in
this view has been clicked and held. Implementers can call
getItemAtPosition(position) if they need to access the data associated
with the selected item.
Parameters
parent The AbsListView where the click happened
view The view within the AbsListView that was clicked
position The position of the view in the list
id The row id of the item that was clicked
Returns true if the callback consumed the long click, false otherwise
So, parent is your ListView. view is the view of the *long clicked' list item. position is the position inside the list and thus also the position in your array. For id I am not sure whether the default implementations returns a constant or the position.
As suggested in gwt documentation, I try to follow the MVP design pattern while creating my application. When using simple tree, the example in the documentation is straight forwards and makes good example of MVP and gwt. In the example the view is created and the data is given to the view to display. As far as I understand this is exactly the way to keep view, model and presenter separated.
With CellTree, the data populating happens inside the TreeViewModel's data provider. Data provider cannot be taken outside the cell tree and therefore I need to do all data populating inside the cell tree, which is in the view. Now, the view needs to know about the model and the MVP patter is broken. I wan't to dynamically populate data to the cell tree prior to showing it to user, I need to edit the data in cell tree and save it later for different format.
My question goes how to implement CellTree, or in general Cell widgets, in MVP design patter?
I have used CellTable with MVP.
UI:
<g:HTMLPanel>
<g:ScrollPanel>
<p1:CellTable ui:field="cellTable" width="100%" styleName="style.cellTable" height="100%" />
</g:ScrollPanel>
</g:HTMLPanel>
View Interface:
public interface SomeCellListView extends IsWidget {
void setPresenter(Presenter listener);
// Method to set the CellTable data
void setCellList(ArrayList<ObjectDTO> list);
public interface Presenter {
void goTo(Place place);
void doSomething(int id);
}
}
View Implementation:
public class SomeCellListViewImpl extends Composite implements SomeCellListView {
... all Ui Binder stuff here
#UiField(provided = true)
CellTable<ObjectDTO>cellTable = new CellTable<ObjectDTO>();
SomeCellListViewImpl(){
TextColumn<ObjectDTO> someColumn= new TextColumn<ObjectDTO>(){
#Override
public String getValue(ObjectDTO o) {
return o.getSomeFieldValue();
}
};
cellTable.addColumn(someColumn, "column1");
... add other columns here
}
// This method is called from Presenter to set CellTable data
public void setCellList(ArrayList<ObjectDTO> list) {
cellTable.setRowCount(list.size(), true);
cellTable.setRowData(0, list);
}
}
Activity (or Presenter):
// Set view and service in the constructor (Get the view from ClientFactory)
public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
// Make RPC call
this.service
.getCellList(new AsyncCallback<ArrayList<ObjectDTO>>(){
#Override
public void onFailure(Throwable caught) {
view.setError("Error fetching details");
}
#Override
public void onSuccess(ArArrayList<ObjectDTO> result) {
view.setCelllist(result);
}
});
view.setPresenter(this);
containerWidget.setWidget(view.asWidget());
}
Here, the view is already created by ClientFactory. View contains just the layout for CellTable. Data is not loaded when view is created. When an Activity is started (aka Presenter), the "start" method is invoked. Here we make the RPC to get Cell data and call a method in the view to set the data.
I've not used CellTree. But you asked in general about Cell widgets. Hence thought of sharing this. Hope this helps.
i have the same issue with OP. I read the MVP tutorial part II, and then try to use CellTable in my application, while still keep the MVP architect. But i confuse at the part: the tutorial use the syntax like Presenter, but why you only use Presenter ?
Could any help me to do this? My code is like:
public CustomClass extends View {
//uses ondraw() to do something
}
For displaying my custom view on the home screen I created a class to extend Broadcast Receiver:
public class customAppWidgetProvider extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.main);
//Here I want to create my custom view class object and I want to add this view to linear layout in main.xml
CustomClass object = new CustomClass(context) ;
LinearLayout layout = new LinearLayout(context) ;
layout.setLayoutParameters(new LayoutParameters(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
layout.addView(object);
views.addview(R.id.linearlayout, (ViewGroup) layout) ;
views.setOnClickPendingIntent(R.id.analog_appwidget,
PendingIntent.getActivity(context, 0,
new Intent(context, AlarmClock.class),
PendingIntent.FLAG_CANCEL_CURRENT));
int[] appWidgetIds = intent.getIntArrayExtra(
AppWidgetManager.EXTRA_APPWIDGET_IDS);
AppWidgetManager gm = AppWidgetManager.getInstance(context);
gm.updateAppWidget(appWidgetIds, views);
}
}
}
But adding ViewGroup to RemoteView reference is not working... The main.xml layout above contains only LinearLayout. I want to add a custom view object to it. But after running this nothing shows on screen...
Please help me to do this. Thanks in Advance.
It's not possible to add a custom View to an app widget. See the "Creating the App Widget Layout" section of the App Widgets Dev Guide for what View types are allowed.
Android 3.0 adds support for some views to display collections. See the "Using App Widgets with Collections" section for details.
Otherwise, to dynamically add an allowed View to an App Widget, after inflating the RemoteViews and getting a reference to it, you can use its addView(View) method, or the addView(View) method on any of the View objects already in the RemoteViews.
I want to access the properties of an image when it is selected from a gridview. For example if I am using.
GridView gridview = (GridView) findViewById(R.id.imageGallery);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position,long id)
{
//need code in here that I can do something like this.
//Get access to the integer value of the R.drawable.myimage
//use that int too do a lookup in a dictionary to check for existance
//can't see to find any code to get at the drawable associated with the image clicked in the grid, did intense debug
And data not easily visible at runtime
}
);
#Reid I think you will want to create a custom adapter (extend BaseAdapter or other) that holds a view class containing the metadata you need to get at, based on the position in the list. Possibly an easier way, but that is what I did in a ListView.. A couple of links:
http://developer.android.com/resources/tutorials/views/hello-gridview.html
http://www.anddev.org/gridview-t5585.html
I have to bind my editor widget objects in property sheet.So that i can the property of my widget from property view.
Please help me on this, if possible provide me some code snippets.
You have a good example in the Getting started with Properties
Using the Properties view is simple enough.
Since it shows properties for the selected object, the first step to using it is to make sure that the workbench selection service knows about the object selected in your view. There’s an entire Eclipse Corner article written on the subject of the selection service
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
getSite().setSelectionProvider(viewer);
viewer.setInput(getViewSite());
}
Once you have your view contributing to the workbench selection, you need to make sure that the objects that your view is selecting contribute properties
(extract)
public class Person implements IPropertySource {
private String name;
private Object street;
private Object city;
public Person(String name) {
this.name = name;
this.street = "";
this.city = "";
}
public Object getEditableValue() {
return this;
}
public IPropertyDescriptor[] getPropertyDescriptors() {
return new IPropertyDescriptor[] {
new TextPropertyDescriptor("name", "Name"),
new TextPropertyDescriptor("street", "Street"),
new TextPropertyDescriptor("city", "City")
};
}
I indicated earlier that this solution is “not necessarily [the] most correct”. This is because, for this to work, my domain object needs to know about the very view-centric (and Eclipse-centric) notion of being a property source; in short, there is a tight-coupling between the model and view and this not a good thing™.
Using adapter is a better approach, as described in this article:
Person should implement IAdaptable.
See also this recent article on how to create a custom property view
how to hack the Properties View to listen only to a specific view.
The isImportant() method is the one which decides whether to create an IPage for the specific IWorkbenchPart or not.
The idea is to override that method and return false for all the workbenchPart that we are not interested in. Lets create the view first:
<view
class="com.eclipse_tips.views.CustomPropertiesView"
icon="icons/sample.gif"
id="com.eclipse-tips.views.customePropertiesView"
name="My Properties View">
</view>
The CustomPropertiesView should extend PropertySheet and override the isImportant():
public class CustomPropertiesView extends PropertySheet {
#Override
protected boolean isImportant(IWorkbenchPart part) {
if (part.getSite().getId().equals(IPageLayout.ID_PROJECT_EXPLORER))
return true;
return false;
}
}
In this case, I'm making the view only to respond to Project Explorer and ignore other views
According to this thread, the same principle should be valid for an Editor instead of a View.
The property sheet listens to the workbench page selection provider.
The selection provider depends on what viewer/editor is active.
Each editor/viewer provides their own selection provider to use when that editor/viewer is active.
This way the property sheet doesn't care who is active, it just listens to the selection provider.
That way depending upon the view, a different set of properties are displayed.
For example, the Navigator view provides IResource selections, so the property sheet then displays IResource properties when the Navigator is active.
The Workbench Selection mechanism is illustrated in this article
The ISelectionListener is a simple interface with just one method.
A typical implementation looks like this:
private ISelectionListener mylistener = new ISelectionListener() {
public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
if (sourcepart != MyView.this && // 1
selection instanceof IStructuredSelection) { // 2
doSomething(((IStructuredSelection) selection).toList()); // 3
}
}
};
Depending on your requirements your listener implementation probably needs to deal with the following issues as shown in the code snippet above:
In case we also provide selections (e.g. a view or editor) we should exclude our own selection events from processing. This avoids unexpected results when the user selects elements within our part (1).
Check whether we can handle this kind of selection (2).
Get the selected content from the selection and process it (3).