Video 360

You can build a application with a video 360.

video 360

You can download the project here

The first step:

We have to put in build.gradle, in dependences this line:

compile files('src/main/libs/panframe-1.9.jar')

Then we have to add video in src/raw

Now in our activity we put this code:

import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.SeekBar;

import com.panframe.android.lib.PFAsset;
import com.panframe.android.lib.PFAssetObserver;
import com.panframe.android.lib.PFAssetStatus;
import com.panframe.android.lib.PFNavigationMode;
import com.panframe.android.lib.PFObjectFactory;
import com.panframe.android.lib.PFView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends ActionBarActivity implements PFAssetObserver, SeekBar.OnSeekBarChangeListener {

    PFView mPfview;
    PFAsset mPfasset;
    PFNavigationMode mCurrentNavigationMode = PFNavigationMode.MOTION;

    boolean 			mUpdateThumb = true;;
    Timer mScrubberMonitorTimer;

    ViewGroup mFrameContainer;
    Button mStopButton;
    Button				mPlayButton;
    Button				mTouchButton;
    SeekBar				mScrubber;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);

        mFrameContainer = (ViewGroup) findViewById(R.id.framecontainer);
        mFrameContainer.setBackgroundColor(0xFF000000);

        mPlayButton = (Button)findViewById(R.id.playbutton);
        mStopButton = (Button)findViewById(R.id.stopbutton);
        mTouchButton = (Button)findViewById(R.id.touchbutton);
        mScrubber = (SeekBar)findViewById(R.id.scrubber);

        mPlayButton.setOnClickListener(playListener);
        mStopButton.setOnClickListener(stopListener);
        mTouchButton.setOnClickListener(touchListener);
        mScrubber.setOnSeekBarChangeListener(this);

        mScrubber.setEnabled(false);

        loadVideo("android.resource://" + getPackageName() + "/" + R.raw.skyrim360);

        showControls(true);
        mPfasset.play();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * Show/Hide the playback controls
     *
     * @param  bShow  Show or hide the controls. Pass either true or false.
     */
    public void showControls(boolean bShow)
    {
        int visibility = View.GONE;

        if (bShow)
            visibility = View.VISIBLE;

        mPlayButton.setVisibility(visibility);
        mStopButton.setVisibility(visibility);
        mTouchButton.setVisibility(visibility);
        mScrubber.setVisibility(visibility);

        if (mPfview != null)
        {
            if (!mPfview.supportsNavigationMode(PFNavigationMode.MOTION))
//				_touchButton.setVisibility(View.GONE);
                Log.d("SimplePlayer", "Not supported nav");
        }
    }

    /**
     * Start the video with a local file path
     *
     * @param  filename  The file path on device storage
     */
    public void loadVideo(String filename)
    {

        mPfview = PFObjectFactory.view(MainActivity.this);
        mPfasset = PFObjectFactory.assetFromUri(this, Uri.parse(filename), this);

        mPfview.displayAsset(mPfasset);
        mPfview.setNavigationMode(mCurrentNavigationMode);

        mFrameContainer.addView(mPfview.getView(), 0);

    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        mUpdateThumb = false;
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        mPfasset.setPLaybackTime(seekBar.getProgress());
        mUpdateThumb = true;
    }

    @Override
    public void onStatusMessage(final PFAsset pfAsset, PFAssetStatus pfAssetStatus) {

        switch (pfAssetStatus)
        {
            case LOADED:
                Log.d("SimplePlayer", "Loaded");
                break;
            case DOWNLOADING:
                Log.d("SimplePlayer", "Downloading 360 movie: "+ mPfasset.getDownloadProgress()+" percent complete");
                break;
            case DOWNLOADED:
                Log.d("SimplePlayer", "Downloaded to "+pfAsset.getUrl());
                break;
            case DOWNLOADCANCELLED:
                Log.d("SimplePlayer", "Download cancelled");
                break;
            case PLAYING:
                Log.d("SimplePlayer", "Playing");
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                mScrubber.setEnabled(true);
                mScrubber.setMax((int) pfAsset.getDuration());
                mPlayButton.setText("pause");
                mScrubberMonitorTimer = new Timer();
                final TimerTask task = new TimerTask() {
                    public void run() {
                        if (mUpdateThumb)
                            mScrubber.setProgress((int) pfAsset.getPlaybackTime());
                    }
                };
                mScrubberMonitorTimer.schedule(task, 0, 33);
                break;
            case PAUSED:
                Log.d("SimplePlayer", "Paused");
                mPlayButton.setText("play");
                break;
            case STOPPED:
                Log.d("SimplePlayer", "Stopped");
                mPlayButton.setText("play");
                mScrubberMonitorTimer.cancel();
                mScrubberMonitorTimer = null;
                mScrubber.setProgress(0);
                mScrubber.setEnabled(false);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                break;
            case COMPLETE:
                Log.d("SimplePlayer", "Complete");
                mPlayButton.setText("play");
                mScrubberMonitorTimer.cancel();
                mScrubberMonitorTimer = null;
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                break;
            case ERROR:
                Log.d("SimplePlayer", "Error");
                break;
        }
    }

    /**
     * Click listener for the play/pause button
     *
     */
    private View.OnClickListener playListener = new View.OnClickListener() {
        public void onClick(View v) {
            if (mPfasset.getStatus() == PFAssetStatus.PLAYING)
            {
                mPfasset.pause();
            }
            else
                mPfasset.play();
        }
    };

    /**
     * Click listener for the stop/back button
     *
     */
    private View.OnClickListener stopListener = new View.OnClickListener() {
        public void onClick(View v) {
            mPfasset.stop();
        }
    };

    /**
     * Click listener for the navigation mode (touch/motion (if available))
     *
     */
    private View.OnClickListener touchListener = new View.OnClickListener() {
        public void onClick(View v) {
//			if (mPfview != null)
//			{

            Button touchButton = (Button)findViewById(R.id.touchbutton);
            if (mCurrentNavigationMode == PFNavigationMode.TOUCH)
            {
                mCurrentNavigationMode = PFNavigationMode.MOTION;
                touchButton.setText("motion");
            }
            else
            {
                mCurrentNavigationMode = PFNavigationMode.TOUCH;
                touchButton.setText("touch");
            }
            mPfview.setNavigationMode(mCurrentNavigationMode);
        }
//		}
    };

    /**
     * Called when pausing the app.
     * This function pauses the playback of the asset when it is playing.
     *
     */
    public void onPause() {
        super.onPause();
        if (mPfasset != null)
        {
            if (mPfasset.getStatus() == PFAssetStatus.PLAYING)
                mPfasset.pause();
        }
    }

    public void  onStartCommand(Intent intent, int flags, int startId) {
        mPfasset.play();
    }

}

You can download the project here

Expandable Listview inside scrollview

Expandable listview inside scrollview

When we have a ListView expandable inside ScrollView, we must make this in our layout, always expandable listview must be the last view in our layout:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_expandable_scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <LinearLayout
        android:id="@+id/LinearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">

<!-- your code --->

 <ExpandableListView
            android:id="@+id/activity_expandable_list_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"/>

    </LinearLayout>
</ScrollView>

In your onCreate

mListView = (ExpandableListView) findViewById(R.id.activity_expandable_list_view);
        MyExpandableListAdapter adapter = new MyExpandableListAdapter(this,
                mGroups);
        mListView.setAdapter(adapter);
        mListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {

            @Override
            public boolean onGroupClick(ExpandableListView parent, View v,
                                        int groupPosition, long id) {
                setListViewHeight(parent, groupPosition);
                return false;
            }
        });

You need this function:

    private void setListViewHeight(ExpandableListView listView,
                                   int group) {
        ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
        int totalHeight = 0;
        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.EXACTLY);
        for (int i = 0; i < listAdapter.getGroupCount(); i++) {
            View groupItem = listAdapter.getGroupView(i, false, null, listView);
            groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);

            totalHeight += groupItem.getMeasuredHeight();

            if (((listView.isGroupExpanded(i)) && (i != group))
                    || ((!listView.isGroupExpanded(i)) && (i == group))) {
                for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
                    View listItem = listAdapter.getChildView(i, j, false, null,
                            listView);
                    listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);

                    totalHeight += listItem.getMeasuredHeight();

                }
            }
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        int height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
        if (height < 10)
            height = 200;
        params.height = height;
        listView.setLayoutParams(params);
        listView.requestLayout();

    }

Download code

ListView inside ScrollView II

See only one item

You do not have to do anything special in layout.xml file nor handle anything on the parent ScrollView. You only have to handle the child ListView. You can also use this code to use any type of child view inside a ScrollView & perform Touch operations.

ScrollView inside ListView

Just add these lines of code in your java class :

listView.setOnTouchListener(new ListView.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // Disallow the touch request for parent scroll on touch of child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });

Download code

ListView inside ScrollView

You Create Custom ListView Which is non Scrollable

http://thedeveloperworldisyours.com/

Download code

public class NonScrollListView extends ListView {

    public NonScrollListView(Context context) {
        super(context);
    }
    public NonScrollListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = View.MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

In Your Layout File

<?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:fadingEdgeLength="0dp"
    android:fillViewport="true"
    android:overScrollMode="never"
    android:scrollbars="none" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <!-- com.Example Changed with your Package name -->

        <com.thedeveloperworldisyours.view.NonScrollListView
            android:id="@+id/lv_nonscroll_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.thedeveloperworldisyours.view.NonScrollListView>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/lv_nonscroll_list" >

            <!-- Your another layout in scroll view -->

        </RelativeLayout>
    </RelativeLayout>

</ScrollView>

In Java File

Create a object of your customListview instead of ListView like :

NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);

Download code

Infinitely Scrolling List

When you use a List or Grid, sometimes common requirement is to dynamically load more data as the user keeps scrolling down making it a potentially infinite scrolling list. This blog will guide you on how to implement this feature in your app.

Infinitely Scrolling List

We will need is our InfiniteScrollListener class that will implement OnScrollListener. Let’s jump right in and see the code for this class.

public abstract class InfiniteScrollListener implements AbsListView.OnScrollListener {
    private int mBufferItemCount = 10;
    private int mCurrentPage = 0;
    private int mItemCount = 0;
    private boolean mIsLoading = true;

    public InfiniteScrollListener(int bufferItemCount) {
        this.mBufferItemCount = bufferItemCount;
    }

    public abstract void loadMore(int page, int totalItemsCount);

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        // Do Nothing
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (totalItemCount < mItemCount) {
            this.mItemCount = totalItemCount;
            if (totalItemCount == 0) {
                this.mIsLoading = true;
            }
        }

        if (mIsLoading && (totalItemCount > mItemCount)) {
            mIsLoading = false;
            mItemCount = totalItemCount;
            mCurrentPage++;
        }

        if (!mIsLoading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + mBufferItemCount)) {
            loadMore(mCurrentPage + 1, totalItemCount);
            mIsLoading = true;
        }
    }

}

Then in our onCreate of Activity We must put this:

mGridView.setOnScrollListener(new InfiniteScrollListener(5) {
            @Override
            public void loadMore(int page, int totalItemsCount) {
                mProgressDialog.show();
                // your code
            }
        });

Download code