How To Save View State During Orientation Change In Android Widget

This one is tricky because I totally was lost until I luckily came across a forum post that explained how Android works behind the scenes during orientation change.

So my Android widget has two layouts, one visible and one hidden. The visible layout is default while the hidden layout will only be shown if data is present.

When orientation change happens (portrait, landscape), the problem is that the hidden layout which I programmaticaly set to visible is not shown.

Use Jona from Stack Overflow mentioned this important note that solved my problem.

“When the screen is rotated and the widget needs to be restored the Android system will restore it using the data from the last RemoteViews update. I was updating parts of the widget separately so when it needed to restore only one part got updated. The fix is always update everything on your RemoteViews all at once.”

So that is the solution. Whenever you instantiate and inflate RemoteViews, be sure that you also set the View states on everything.

Donations appreciated. Every little $ helps. Or click Google +1. Or play the short video on the upper right of this page.

Save JTree Tree Node State

The JTree class does not have a means to save a tree node’s state (e.g. expanded of collapsed). I did come across a forum where a post mentioned about the use of a TreeExpansionListener to save a tree node’s state and provided a short sample snippet. I modified some minor bugs and the code below is the finished and modified code.

Say you want to add a new tree node, you do not want the JTree to refresh all its tree nodes’ expanded state to collapsed. Rather, the previous state will still be the same even when a new tree node is added to the JTree. You can call the method jTree1.restoreExpansionState() to restore it and jTree1.resetExpansionState() to reset all the state to collapsed.

public class MyJTree extends JTree {
    private List expandedTreeObjects;
    public LinkedHashMap treepaths;
    private boolean supressExpansionEvent;
    private DefaultMutableTreeNode root;
 
    public My JTree(DefaultMutableTreeNode root) {
        // create root of tree
        this.root = root;
        setModel(new DefaultTreeModel(root));
 
        expandedTreeObjects = new LinkedList();
        treepaths = new LinkedHashMap();
 
        // add expansion listener to preserve expansion state of each node
        addTreeExpansionListener(new TreeExpansionListener() {
            @Override
            public void treeExpanded(TreeExpansionEvent event) {
                processTreeExpansion(event);
            }
 
            @Override
            public void treeCollapsed(TreeExpansionEvent event) {
                processTreeCollapse(event);
            }
        });
    }
 
    public void expandRoot() {
        //expand path to root
        expandPath(new TreePath(((DefaultMutableTreeNode) ((DefaultTreeModel) getModel()).getRoot()).getPath()));
    }
 
    private void restoreTreeNode(JTree tree, TreePath parent, DefaultMutableTreeNode treeNode) {
        // Traverse down through the children
        TreeNode node = (TreeNode) parent.getLastPathComponent(); // Get the last TreeNode component for this path
 
        if (node.getChildCount() >= 0) { // If the node has children?
            // Create a child numerator over the node
            Enumeration en = node.children();
            while (en.hasMoreElements()) { // While we have children
                DefaultMutableTreeNode dmTreeNode = (DefaultMutableTreeNode)en.nextElement(); // Derive the node
                TreePath path = parent.pathByAddingChild(dmTreeNode); // Derive the path
                restoreTreeNode(tree, path, dmTreeNode); // Recursive call with new path
 
            } // End While we have more children
        } // End If the node has children?
 
        // Nodes need to be expand from last branch node up
        if (treeNode != null) { // If true, this is the root node - ignore it
            String myString = new TreePath(treeNode.getPath()).toString();
 
            if (expandedTreeObjects.contains(myString)) { // Is this present on the previously expanded list?
                tree.expandPath(parent); // et viola
            }
        }
    }
 
    private void processTreeExpansion(TreeExpansionEvent e){
 
        if (supressExpansionEvent == false) {
            TreePath p = (TreePath) e.getPath();
            expandedTreeObjects.add(p.toString());
        }
 
    }
 
    private void processTreeCollapse(TreeExpansionEvent e){
        TreePath p = (TreePath) e.getPath();
        expandedTreeObjects.remove(p.toString());
    }
 
    public void restoreExpansionState() {
        supressExpansionEvent = true;
 
        ((DefaultTreeModel) getModel()).reload();
        restoreTreeNode(this, new TreePath(root), null);
 
        supressExpansionEvent = false; // Now we can go back to responding normally to expansion events
    }
 
    public void resetExpansionState() {
        expandedTreeObjects.clear();
    }
 
}

Donations appreciated. Every little $ helps. Or click Google +1. Or play the short video on the upper right of this page.

Related Posts Plugin for WordPress, Blogger...