experimental: inline video player

This commit is contained in:
Andrew Dolgov 2017-05-31 22:51:23 +03:00
parent a4609d054e
commit 9420b9570e
6 changed files with 235 additions and 11 deletions

View File

@ -13,6 +13,7 @@ import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -36,6 +37,8 @@ import android.view.Display;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@ -78,6 +81,7 @@ import org.fox.ttrss.types.ArticleList;
import org.fox.ttrss.types.Feed;
import org.fox.ttrss.util.HeadlinesRequest;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -126,6 +130,9 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
private View m_topChangedView;
private View m_amrFooterView;
private MediaPlayer m_mediaPlayer;
private SurfaceView m_activeSurface;
public ArticleList getSelectedArticles() {
ArticleList tmp = new ArticleList();
@ -708,6 +715,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
public View headlineHeader;
public View topChangedMessage;
public View flavorImageOverflow;
public SurfaceView flavorVideoView;
public int position;
public boolean flavorImageEmbedded;
}
@ -933,6 +941,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
holder.headlineHeader = v.findViewById(R.id.headline_header);
holder.topChangedMessage = v.findViewById(R.id.headlines_row_top_changed);
holder.flavorImageOverflow = v.findViewById(R.id.flavor_image_overflow);
holder.flavorVideoView = (SurfaceView) v.findViewById(R.id.flavor_video);
v.setTag(holder);
@ -1106,6 +1115,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
holder.flavorImageView.setVisibility(View.GONE);
holder.flavorVideoKindView.setVisibility(View.GONE);
holder.flavorImageOverflow.setVisibility(View.GONE);
holder.flavorVideoView.setVisibility(View.GONE);
holder.headlineHeader.setBackgroundDrawable(null);
// this is needed if our flavor image goes behind base listview element
@ -1176,6 +1186,61 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
holder.flavorImageLoadingBar.setVisibility(View.VISIBLE);
holder.flavorImageLoadingBar.setIndeterminate(true);
/*if ("video".equals(article.flavorImage.tagName().toLowerCase()) && article.flavorStreamUri != null) {
final MediaPlayer mediaPlayer = new MediaPlayer();
holder.flavorVideoView.setVisibility(View.VISIBLE);
repositionFlavorVideo(holder.flavorVideoView, holder);
try {
mediaPlayer.setDataSource(article.flavorStreamUri);
} catch (IOException e) {
e.printStackTrace();
}
final View bar = holder.flavorImageLoadingBar;
SurfaceHolder sh = holder.flavorVideoView.getHolder();
sh.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
try {
mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
bar.setVisibility(View.GONE);
//resizeSurface();
mp.setLooping(true);
mp.start();
}
}
);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//
}
});
} else { */
holder.flavorImageView.setVisibility(View.VISIBLE);
holder.flavorImageView.setImageDrawable(null);
@ -1208,7 +1273,9 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
holder.flavorImageView.setVisibility(View.VISIBLE);
holder.flavorImageOverflow.setVisibility(View.VISIBLE);
maybeRepositionFlavorImage(holder.flavorImageView, resource, holder);
boolean forceDown = article.flavorImage != null && "video".equals(article.flavorImage.tagName().toLowerCase());
maybeRepositionFlavorImage(holder.flavorImageView, resource, holder, forceDown);
adjustVideoKindView(holder, article);
return false;
@ -1220,14 +1287,108 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
.into(glideImage);
}
holder.flavorImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (m_prefs.getBoolean("inline_video_player", false) && article.flavorImage != null &&
"video".equals(article.flavorImage.tagName().toLowerCase()) && article.flavorStreamUri != null) {
holder.flavorImageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
openGalleryForType(article, holder, null);
return true;
}
});
holder.flavorImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (m_mediaPlayer != null) {
m_mediaPlayer.release();
}
if (m_activeSurface != null) {
m_activeSurface.setVisibility(View.GONE);
}
m_mediaPlayer = new MediaPlayer();
try {
m_mediaPlayer.setDataSource(article.flavorStreamUri);
} catch (IOException e) {
e.printStackTrace();
}
SurfaceHolder sh = holder.flavorVideoView.getHolder();
holder.flavorVideoView.setVisibility(View.VISIBLE);
final ProgressBar bar = holder.flavorImageLoadingBar;
bar.setIndeterminate(true);
bar.setVisibility(View.VISIBLE);
holder.flavorVideoView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (m_mediaPlayer.isPlaying())
m_mediaPlayer.pause();
else
m_mediaPlayer.start();
}
});
m_activeSurface = holder.flavorVideoView;
sh.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
m_mediaPlayer.setDisplay(holder);
try {
m_mediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
e.printStackTrace();
}
m_mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
bar.setVisibility(View.GONE);
//resizeSurface();
mp.setLooping(true);
mp.start();
}
}
);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
bar.setVisibility(View.GONE);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
bar.setVisibility(View.GONE);
m_mediaPlayer.release();
}
});
}
});
} else {
holder.flavorImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
openGalleryForType(article, holder, null);
}
});
}
});
}
}
String articleAuthor = article.author != null ? article.author : "";
@ -1390,7 +1551,15 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
return px;
}
private void maybeRepositionFlavorImage(View view, GlideDrawable resource, HeadlineViewHolder holder) {
private void repositionFlavorVideo(View view, HeadlineViewHolder holder) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
lp.addRule(RelativeLayout.BELOW, R.id.headline_header);
view.setLayoutParams(lp);
}
private void maybeRepositionFlavorImage(View view, GlideDrawable resource, HeadlineViewHolder holder, boolean forceDown) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams();
int w = resource.getIntrinsicWidth();
@ -1399,7 +1568,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
//Log.d(TAG, "XYR: " + pxToDp(w) + " " + pxToDp(h) + " " + r);
if (h < m_minimumHeightToEmbed || r >= 1.2) {
if (forceDown || h < m_minimumHeightToEmbed || r >= 1.2) {
lp.addRule(RelativeLayout.BELOW, R.id.headline_header);
@ -1567,6 +1736,22 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING || scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
/*if (m_activeSurface != null) {
m_activeSurface.setVisibility(View.GONE);
}*/
try {
if (m_mediaPlayer != null && m_mediaPlayer.isPlaying()) {
m_mediaPlayer.pause();
}
} catch (IllegalStateException e) {
// i guess it was already released, oh well
}
}
if (scrollState == SCROLL_STATE_IDLE && m_prefs.getBoolean("headlines_mark_read_scroll", false)) {
if (!m_readArticles.isEmpty()) {
m_activity.toggleArticlesUnread(m_readArticles);

View File

@ -159,7 +159,7 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList
HeadlinesFragment hf = new HeadlinesFragment();
if (BuildConfig.DEBUG) {
hf.initialize(new Feed(-4, "All articles", false));
hf.initialize(new Feed(-1, "Starred articles", false));
} else {
hf.initialize(new Feed(-3, getString(R.string.fresh_articles), false));
}

View File

@ -261,7 +261,7 @@ public class VideoPlayerActivity extends CommonActivity {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//
mediaPlayer.release();
}
});

View File

@ -56,6 +56,22 @@
android:src="@drawable/drawer_header"
android:visibility="visible" />
<SurfaceView
android:id="@+id/flavor_video"
android:foreground="@drawable/ripple"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:background="@android:color/transparent"
android:cropToPadding="true"
android:src="@drawable/drawer_header"
android:scaleType="fitCenter"
android:visibility="gone"
android:layout_alignBottom="@+id/flavor_image"
android:layout_alignTop="@+id/flavor_image" />
<RelativeLayout
android:id="@+id/headline_header"
android:clickable="true"

View File

@ -57,6 +57,22 @@
android:src="@drawable/drawer_header"
android:visibility="visible" />
<SurfaceView
android:id="@+id/flavor_video"
android:foreground="@drawable/ripple"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:background="@android:color/transparent"
android:cropToPadding="true"
android:src="@drawable/drawer_header"
android:scaleType="fitCenter"
android:visibility="gone"
android:layout_alignBottom="@+id/flavor_image"
android:layout_alignTop="@+id/flavor_image" />
<RelativeLayout
android:id="@+id/headline_header"
android:clickable="true"

View File

@ -134,6 +134,12 @@
android:key="open_fresh_on_startup"
android:title="@string/prefs_open_fresh_on_startup" />
<org.fox.ttrss.util.LessBrokenSwitchPreference
android:defaultValue="false"
android:key="inline_video_player"
android:summary="Experimental: play videos inside headlines list. Long tap to open separate player"
android:title="Inline video player" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/reading" >
<org.fox.ttrss.util.FontSizeDialogPreference
@ -218,6 +224,7 @@
android:summary="@string/prefs_widget_show_fresh_summary" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/debugging" >
<org.fox.ttrss.util.LessBrokenSwitchPreference
android:defaultValue="true"
android:key="webview_hardware_accel"