Dynamically adding a custom view to RemoteViews - android-widget

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.

Related

Custom Perspective Switcher Toolbar: How can I dynamically update it?

I'm trying to implement a custom perspective switcher toolbar to replace eclipse's built-in one. I couldn't get the toolbar to display, and it was shown to me that due to a bug with the dynamic element in a menu contribution, I have to use a control element instead, as described in the workaround to the dynamic bug.
I have a toolbar displaying following that approach, but I cannot figure out how to update it dynamically. The workaround instruction is to call ContributionItem#fill(CoolBar, int) from my WorkbenchControlContributionItem's update method instead of doing the fill in the createControl method.
I don't know who is supposed to call update, but it never gets invoked no matter what I do. I have a perspective listener which knows when to update the toolbar, so from that listener's callback I call fill(CoolBar, int). But I wasn't sure how to get the CoolBar to pass to that method, so I created one on the current shell.
The end result of all this is that the toolbar displays the correct number of items initially, but when I need to add an item, it has no effect. I call fill(CoolBar, int) and it adds the new item to the toolbar, but everything I've tried to make the CoolBar and ToolBarupdate does not work. When I re-launch the app, the toolbar has the added item.
I'm sure I'm doing this wrong, but I can't figure out the right way. Here's an elided representation of my code (omitting methods, layout code, etc not related to the update problem).
public class PerspectiveSwitcherToolbar extends WorkbenchWindowControlContribution implements IPerspectiveListener {
...
#Override
protected Control createControl(Composite parent) {
this.parent = parent;
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.getWorkbenchWindow().addPerspectiveListener(this);
toolBarManager = (ToolBarManager)parent.getParent().getData();
fTopControl = new Composite(parent, SWT.BORDER);
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
return fTopControl;
}
#Override
public void fill(CoolBar coolbar, int index) {
IPerspectiveDescriptor[] openPerspectives = page.getOpenPerspectives();
String activePerspective = getPerspectiveId();
ToolBar toolbar = new ToolBar(fTopControl, SWT.NONE);
for(IPerspectiveDescriptor descriptor : openPerspectives) {
ToolItem item = new ToolItem(toolbar, SWT.RADIO);
//overkill here, trying to find some way to upate the toolbar
toolbar.update();
parent.update();
parent.layout(true);
parent.getParent().update();
parent.getParent().layout(true);
coolbar.layout(true);
}
//PerspectiveListener callback
#Override
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
fill(new CoolBar(page.getWorkbenchWindow().getShell(), SWT.HORIZONTAL), -1);
if (page.getWorkbenchWindow() instanceof WorkbenchWindow){
//this non-API call doesn't help either
((WorkbenchWindow) page.getWorkbenchWindow()).updateActionBars();
}
}
...
}

MvvmCross navigation on screen

Our designer created a layout something like the screen above. The main idea was to create an application with only one screen, just the red part of the screen is changing (i.e. 2 textbox instead of 1 textbox) when you tap on a button. This application will be a multiplatform application and I'm using MvvmCross to create it. My question is that how can i achieve this behavior in Mvvm? My first thought was sg. like the code below, but I'm not satisfied with this solution. Do you have any better solution to this problem? Should i somehow overwrite default navigation on ShowViewModel()?
public class MainViewModel : MvxViewModel
{
private MvxViewModel _currentViewModel;
public MvxViewModel CurrentViewModel
{
get { return _currentViewModel; }
set { _currentViewModel = value; RaisePropertyChanged(() => CurrentViewModel); }
}
public MainViewModel()
{
CurrentViewModel = new DefaultViewModel();
}
public void OnButtonClick()
{
CurrentViewModel = new SecondViewModel();
}
}
public partial class MainViewModel : MvxViewController
{
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
FirstViewModel.WeakSubscribe(ViewModelPropertyChanged);
}
private void ViewModelPropertyChanged(object sender, PropertyChangedEventArgs args)
{
if (args.PropertyName == "CurrentViewModel")
{
if (Model.CurrentViewModel != null)
{
if (Model.CurrentViewModel is SecondViewModel)
{
//remove bindings
//change View
//bind new viewmodel
}
}
}
}
The alternatives for this kind of 'non-page navigation' are similar to those in MvvmCross Dialog:
You can:
Customize the MvxPresenter to allow ShowViewModel to be used
Put a special interface in the Core project and use Inversion of Control to inject the implementation from the UI project to the Core project
Use the MvxMessenger plugin and share messages between the Core and UI project which trigger this type of navigation.
Use a property with a special interface (like IInteractionRequest) on the ViewModel - that property will fire an event when the UI needs to change.
Personally, for your situation, I quite like the first of these options - intercepting ShowViewModel using a presenter.
One other alternative which I might consider is to use some kind of 'Adapter-driven' control which could very easily update it's child contents based on the CurrentViewModel property. On Android, this would be as easy as using an MvxLinearLayout with an adapter. On iOS, however, I think you'd have to write something new to do this - just because iOS doesn't really have a LinearLayout/StackPanel control.

How to create CellTree with MVP pattern

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 ?

How to switch to a different view and controller in GWT?

I have a widget written in GWT. In the implementation of EntryPoint, I have the widget load a controller and a view that is tied to that controller. I add this view to the RootPanel and it works fine.
public class EntryImpl implements EntryPoint {
SimplePanel simplePanel;
View view;
Controller controller;
public final void onModuleLoad()
{
controller = createController();
view = createViewForController(controller);
simplePanel = new SimplePanel();
simplePanel.add(view);
RootPanel.get().add(simplePanel);
}
}
Something like above. Now I want to change the view and controller, say if the user clicks a button to load a different view. I tried something along the lines of adding an Anchor and handling the ClickEvent as follows:
public void onClick(Widget sender) {
simplePanel.remove(view);
controller = createController();
view = createViewForController(controller);
panel.add(view);
}
Is this the right way to go about doing this, or is there a better way? So far, this isn't working for me-- my new view is not showing up.
Thanks
You can use DeckPanel and switch the view using showWidget(index) method. Enabling deck panel's animations can improve usability.
what is panel in your OnClick event? if you just want to see the view you can get the root panel and see it RootPanel.get().add(view), Adding a div in the base HTML page may serve your purpose , if you have div you can add your view inside that div by RootPanel.get("div").add(view)...
You can use mvp pattern to control view transition (I have not used it yet)
http://code.google.com/intl/en/webtoolkit/articles/mvp-architecture.html

Identify which instance of the view is currently active in RCP?

I am creating an RCP application. I need to open multiple instances of the same view but with different data. I did it by setting secondary id for different instances of the same view. Specifically, my problem is as follows: Please take a look
I have a graph view called Views.GraphView. I opened different instances of it from a command called openGraphView to show different graphs. The command is as follows:
page.showView("Views.GraphView", Integer.toString(instanceNum++), IWorkbenchPage.VIEW_ACTIVATE);
Now, I have a command called TreeLayout on this Views.GraphView toolbar, which suppose to change the layout of the graph and it will operate on each instance of the view. But for this, I think, I need to identify which instance of the view is active. The TreeLayout command looks something like this:
IViewPart findView = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage(). findView( "Views.GraphView"); //I think in the findView I need to give the id of the view [but how can I put the secondary id?]
GraphView view = (GraphView) findView;
view.changeLayout(); //I wrote this method in the graph view to change the layout
//I just tried to print the secondary id, but it did not print anyting
System.out.println("From treelayout command:- " + view.getViewSite().getSecondaryId());
So how can I identify which instance of the view is currently active and to operate on it?
You can use IWorkBenchPage.findViewReference(String viewId, String viewId) , if it returns null, the view with viewId and viewId is not present in the current perspective.
If you have a ViewReference you can use ViewReference.getView(boolean restore) to get the view
so in your handler you get something like:
final IWorkbenchPage page = HandlerUtil.getActiveWorkbenchWindow(
event).getActivePage();
final int instanceNum = 8;//the number of instances that are created
for (int index = 0; index < instanceNum; index++) {
final IViewReference viewReference = page.findViewReference(
"Views.GraphView", Integer.toString(index));
if (viewReference != null) {
final IViewPart view = viewReference.getView(true);
if (view instanceof GraphView) {
final GraphView graphView = (GraphView) view;
graphView.changeLayout();
}
}
}
The view.getViewSite().getSecondaryId() method is the good one to identify a secondary view. This method only returns the Null string for the "primary" view: the one opened when user click Window -> Show View - Your View.
I don't understand why your view toolbar button has to operate on all the view instances. TO my eyes, you should have one button in each view instance toolbar operating only in its own view. If you really need to operate from one button to ALL the views I think you will have to keep the open views references yourself, because I think the workbench doesn't provide a findViews method returning a view array.
using the below code you should be able to get the current active view.
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart()
Active view and Editor name display on MessageDialogbox
public class Active_Workbench extends AbstractHandler{
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
// A part service tracks the creation and activation of parts within a workbench page.
IPartService service = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService();
MessageDialog.openInformation(HandlerUtil.getActiveWorkbenchWindow(
event).getShell(), "Current Workbench Window", service.getActivePart().getTitle().toString());
return null;
}
}
I hope this answer is useful.