animate item button and made channel layout use recyclerview propper

This commit is contained in:
Christian Schabesberger 2016-08-03 15:32:25 +02:00
parent 1ab82dfa32
commit 5d06e8310d
8 changed files with 165 additions and 350 deletions

View File

@ -46,6 +46,8 @@ public class ChannelActivity extends AppCompatActivity {
private int serviceId = -1;
private String channelUrl = "";
private int pageNumber = 0;
private boolean isLoading = false;
private ImageLoader imageLoader = ImageLoader.getInstance();
private InfoListAdapter infoListAdapter = null;
@ -63,7 +65,8 @@ public class ChannelActivity extends AppCompatActivity {
infoListAdapter = new InfoListAdapter(this, rootView);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(infoListAdapter);
infoListAdapter.setOnItemSelectedListener(new InfoListAdapter.OnItemSelectedListener() {
@Override
@ -76,7 +79,92 @@ public class ChannelActivity extends AppCompatActivity {
}
});
// detect if list has ben scrolled to the bottom
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int pastVisiblesItems, visibleItemCount, totalItemCount;
super.onScrolled(recyclerView, dx, dy);
if(dy > 0) //check for scroll down
{
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount && !isLoading)
{
pageNumber++;
Log.d(TAG, "bottomn");
}
}
}
});
requestData(pageNumber);
}
private void updateUi(final ChannelInfo info) {
isLoading = false;
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
ImageView channelBanner = (ImageView) findViewById(R.id.channel_banner_image);
FloatingActionButton feedButton = (FloatingActionButton) findViewById(R.id.channel_rss_fab);
ImageView avatarView = (ImageView) findViewById(R.id.channel_avatar_view);
ImageView haloView = (ImageView) findViewById(R.id.channel_avatar_halo);
progressBar.setVisibility(View.GONE);
if(info.channel_name != null && !info.channel_name.isEmpty()) {
ctl.setTitle(info.channel_name);
}
if(info.banner_url != null && !info.banner_url.isEmpty()) {
imageLoader.displayImage(info.banner_url, channelBanner,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.avatar_url != null && !info.avatar_url.isEmpty()) {
avatarView.setVisibility(View.VISIBLE);
haloView.setVisibility(View.VISIBLE);
imageLoader.displayImage(info.avatar_url, avatarView,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.feed_url != null && !info.feed_url.isEmpty()) {
feedButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, info.feed_url);
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(info.feed_url));
startActivity(i);
}
});
} else {
feedButton.setVisibility(View.GONE);
}
initVideos(info);
}
private void initVideos(final ChannelInfo info) {
infoListAdapter.addStreamItemList(info.related_streams);
}
private void postNewErrorToast(Handler h, final int stringResource) {
h.post(new Runnable() {
@Override
public void run() {
Toast.makeText(ChannelActivity.this,
stringResource, Toast.LENGTH_LONG).show();
}
});
}
private void requestData(int page) {
// start processing
isLoading = true;
Thread channelExtractorThread = new Thread(new Runnable() {
Handler h = new Handler();
@ -122,65 +210,4 @@ public class ChannelActivity extends AppCompatActivity {
channelExtractorThread.start();
}
private void updateUi(final ChannelInfo info) {
StreamInfoItemViewCreator viCreator =
new StreamInfoItemViewCreator(LayoutInflater.from(this), this, rootView);
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
ImageView channelBanner = (ImageView) findViewById(R.id.channel_banner_image);
FloatingActionButton feedButton = (FloatingActionButton) findViewById(R.id.channel_rss_fab);
ImageView avatarView = (ImageView) findViewById(R.id.channel_avatar_view);
ImageView haloView = (ImageView) findViewById(R.id.channel_avatar_halo);
progressBar.setVisibility(View.GONE);
if(info.channel_name != null && !info.channel_name.isEmpty()) {
ctl.setTitle(info.channel_name);
}
if(info.banner_url != null && !info.banner_url.isEmpty()) {
imageLoader.displayImage(info.banner_url, channelBanner,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.avatar_url != null && !info.avatar_url.isEmpty()) {
avatarView.setVisibility(View.VISIBLE);
haloView.setVisibility(View.VISIBLE);
imageLoader.displayImage(info.avatar_url, avatarView,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.feed_url != null && !info.feed_url.isEmpty()) {
feedButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, info.feed_url);
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(info.feed_url));
startActivity(i);
}
});
} else {
feedButton.setVisibility(View.GONE);
}
initVideos(info, viCreator);
}
private void initVideos(final ChannelInfo info, StreamInfoItemViewCreator viCreator) {
infoListAdapter.addStreamItemList(info.related_streams);
}
private void postNewErrorToast(Handler h, final int stringResource) {
h.post(new Runnable() {
@Override
public void run() {
Toast.makeText(ChannelActivity.this,
stringResource, Toast.LENGTH_LONG).show();
}
});
}
}

View File

@ -1,217 +0,0 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Intent;
import android.content.res.TypedArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
/**
* Created by Christian Schabesberger on 24.10.15.
*
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
* StreamInfoItemViewCreator.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class StreamInfoItemViewCreator {
private class ViewHolder {
public ImageView itemThumbnailView;
public TextView itemVideoTitleView,
itemUploaderView,
itemDurationView,
itemUploadDateView,
itemViewCountView;
}
private View rootView = null; //root view of the activty
private Activity activity = null;
private final LayoutInflater inflater;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheInMemory(true).build();
public StreamInfoItemViewCreator(LayoutInflater inflater, Activity a, View rootView) {
this.inflater = inflater;
activity = a;
this.rootView = rootView;
}
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, final StreamPreviewInfo info) {
ViewHolder holder;
// generate holder
if(convertView == null) {
convertView = inflater.inflate(R.layout.video_item, parent, false);
holder = new ViewHolder();
holder.itemThumbnailView = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
holder.itemVideoTitleView = (TextView) convertView.findViewById(R.id.itemVideoTitleView);
holder.itemUploaderView = (TextView) convertView.findViewById(R.id.itemUploaderView);
holder.itemDurationView = (TextView) convertView.findViewById(R.id.itemDurationView);
holder.itemUploadDateView = (TextView) convertView.findViewById(R.id.itemUploadDateView);
holder.itemViewCountView = (TextView) convertView.findViewById(R.id.itemViewCountView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// fill holder with information
holder.itemVideoTitleView.setText(info.title);
if(info.uploader != null && !info.uploader.isEmpty()) {
holder.itemUploaderView.setText(info.uploader);
} else {
holder.itemUploaderView.setVisibility(View.INVISIBLE);
}
if(info.duration > 0) {
holder.itemDurationView.setText(getDurationString(info.duration));
} else {
if(info.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM) {
holder.itemDurationView.setText(R.string.duration_live);
} else {
holder.itemDurationView.setVisibility(View.GONE);
}
}
if(info.view_count >= 0) {
holder.itemViewCountView.setText(shortViewCount(info.view_count));
} else {
holder.itemViewCountView.setVisibility(View.GONE);
}
if(info.upload_date != null && !info.upload_date.isEmpty()) {
holder.itemUploadDateView.setText(info.upload_date + "");
}
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
if(info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
imageLoader.displayImage(info.thumbnail_url,
holder.itemThumbnailView,
displayImageOptions,
new ImageErrorLoadingListener(activity, rootView, info.service_id));
}
return convertView;
}
public View setupView(View convertView, final StreamPreviewInfo info) {
convertView.setClickable(true);
convertView.setFocusable(true);
int[] attrs = new int[]{R.attr.selectableItemBackground};
TypedArray typedArray = activity.obtainStyledAttributes(attrs);
int backgroundResource = typedArray.getResourceId(0, 0);
convertView.setBackgroundResource(backgroundResource);
typedArray.recycle();
convertView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Intent detailIntent = new Intent(activity, VideoItemDetailActivity.class);
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, info.webpage_url);
detailIntent.putExtra(
VideoItemDetailFragment.STREAMING_SERVICE, info.service_id);
activity.startActivity(detailIntent);
return true;
}
return false;
}
});
ImageView rthumb = (ImageView) convertView.findViewById(R.id.itemThumbnailView);
imageLoader.displayImage(info.thumbnail_url, rthumb,
displayImageOptions, new ImageErrorLoadingListener(activity, rootView, info.service_id));
return convertView;
}
public static String shortViewCount(Long viewCount){
if(viewCount >= 1000000000){
return Long.toString(viewCount/1000000000)+"B views";
}else if(viewCount>=1000000){
return Long.toString(viewCount/1000000)+"M views";
}else if(viewCount>=1000){
return Long.toString(viewCount/1000)+"K views";
}else {
return Long.toString(viewCount)+" views";
}
}
public static String getDurationString(int duration) {
String output = "";
int days = duration / (24 * 60 * 60); /* greater than a day */
duration %= (24 * 60 * 60);
int hours = duration / (60 * 60); /* greater than an hour */
duration %= (60 * 60);
int minutes = duration / 60;
int seconds = duration % 60;
//handle days
if(days > 0) {
output = Integer.toString(days) + ":";
}
// handle hours
if(hours > 0 || !output.isEmpty()) {
if(hours > 0) {
if(hours >= 10 || output.isEmpty()) {
output += Integer.toString(hours);
} else {
output += "0" + Integer.toString(hours);
}
} else {
output += "00";
}
output += ":";
}
//handle minutes
if(minutes > 0 || !output.isEmpty()) {
if(minutes > 0) {
if(minutes >= 10 || output.isEmpty()) {
output += Integer.toString(minutes);
} else {
output += "0" + Integer.toString(minutes);
}
} else {
output += "00";
}
output += ":";
}
//handle seconds
if(output.isEmpty()) {
output += "0:";
}
if(seconds >= 10) {
output += Integer.toString(seconds);
} else {
output += "0" + Integer.toString(seconds);
}
return output;
}
}

View File

@ -41,7 +41,6 @@ import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import java.util.ArrayList;
import java.util.Vector;
import org.schabi.newpipe.ActivityCommunicator;
@ -50,13 +49,11 @@ import org.schabi.newpipe.ErrorActivity;
import org.schabi.newpipe.ImageErrorLoadingListener;
import org.schabi.newpipe.Localization;
import org.schabi.newpipe.R;
import org.schabi.newpipe.StreamInfoItemViewCreator;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.AudioStream;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.VideoStream;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.player.BackgroundPlayer;
@ -128,9 +125,6 @@ public class VideoItemDetailFragment extends Fragment {
private void updateInfo(final StreamInfo info) {
try {
Context c = getContext();
StreamInfoItemViewCreator videoItemViewCreator =
new StreamInfoItemViewCreator(LayoutInflater.from(getActivity()),
getActivity(), rootView);
RelativeLayout textContentLayout =
(RelativeLayout) activity.findViewById(R.id.detailTextContentLayout);
@ -155,8 +149,7 @@ public class VideoItemDetailFragment extends Fragment {
View nextVideoView = null;
Button channelButton = (Button) activity.findViewById(R.id.channelButton);
if(info.next_video != null) {
nextVideoView = videoItemViewCreator
.getViewFromVideoInfoItem(null, nextVideoFrame, info.next_video);
nextVideoView.setVisibility(View.GONE);
} else {
activity.findViewById(R.id.detailNextVidButtonAndContentLayout).setVisibility(View.GONE);
activity.findViewById(R.id.detailNextVideoTitle).setVisibility(View.GONE);
@ -267,7 +260,7 @@ public class VideoItemDetailFragment extends Fragment {
textContentLayout.setVisibility(View.VISIBLE);
if(info.related_streams != null && !info.related_streams.isEmpty()) {
initSimilarVideos(info, videoItemViewCreator);
initSimilarVideos(info);
} else {
activity.findViewById(R.id.detailSimilarTitle).setVisibility(View.GONE);
activity.findViewById(R.id.similar_streams_view).setVisibility(View.GONE);
@ -550,7 +543,7 @@ public class VideoItemDetailFragment extends Fragment {
return 0;
}
private void initSimilarVideos(final StreamInfo info, StreamInfoItemViewCreator videoItemViewCreator) {
private void initSimilarVideos(final StreamInfo info) {
similarStreamsAdapter.addStreamItemList(info.related_streams);
}

View File

@ -2,6 +2,7 @@ package org.schabi.newpipe.info_list;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
@ -18,7 +19,7 @@ public class InfoItemHolder extends RecyclerView.ViewHolder {
itemDurationView,
itemUploadDateView,
itemViewCountView;
public View mainLayout;
public Button itemButton;
public InfoItemHolder(View v) {
super(v);
@ -28,6 +29,6 @@ public class InfoItemHolder extends RecyclerView.ViewHolder {
itemDurationView = (TextView) v.findViewById(R.id.itemDurationView);
itemUploadDateView = (TextView) v.findViewById(R.id.itemUploadDateView);
itemViewCountView = (TextView) v.findViewById(R.id.itemViewCountView);
mainLayout = v.findViewById(R.id.item_main_layout);
itemButton = (Button) v.findViewById(R.id.item_button);
}
}

View File

@ -11,7 +11,6 @@ import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.ImageErrorLoadingListener;
import org.schabi.newpipe.R;
import org.schabi.newpipe.StreamInfoItemViewCreator;
import org.schabi.newpipe.extractor.AbstractVideoInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo;
@ -80,7 +79,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
holder.itemUploaderView.setVisibility(View.INVISIBLE);
}
if(info.duration > 0) {
holder.itemDurationView.setText(StreamInfoItemViewCreator.getDurationString(info.duration));
holder.itemDurationView.setText(getDurationString(info.duration));
} else {
if(info.stream_type == AbstractVideoInfo.StreamType.LIVE_STREAM) {
holder.itemDurationView.setText(R.string.duration_live);
@ -105,7 +104,7 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
new ImageErrorLoadingListener(activity, rootView, info.service_id));
}
holder.mainLayout.setOnClickListener(new View.OnClickListener() {
holder.itemButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemSelectedListener.selected(info.webpage_url);

View File

@ -87,21 +87,10 @@
android:layout_centerInParent="true"
android:indeterminate="true"/>
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
<android.support.v7.widget.RecyclerView
android:id="@+id/channel_streams_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/channel_content_view"
android:visibility="visible">
<android.support.v7.widget.RecyclerView
android:id="@+id/channel_streams_view"
android:orientation="vertical"
android:layout_gravity="fill_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>
android:scrollbars="vertical"/>
</android.support.design.widget.CoordinatorLayout>

View File

@ -181,55 +181,66 @@
android:text="100" />
</LinearLayout>
<RelativeLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/linearLayout"
android:id="@+id/detailUploaderWrapView"
android:layout_marginTop="12dp">
<View
android:background="#000"
android:id="@+id/detailUploaderFrame"
android:layout_below="@+id/linearLayout">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="1px" />
<de.hdodenhof.circleimageview.CircleImageView android:id="@+id/detailUploaderThumbnailView"
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
android:layout_width="@dimen/video_item_detail_uploader_image_size"
android:layout_height="@dimen/video_item_detail_uploader_image_size"
android:src="@drawable/buddy"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"/>
<TextView android:id="@+id/detailUploaderView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="@dimen/video_item_detail_uploader_text_size"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Uploader"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/detailUploaderThumbnailView"
android:layout_toEndOf="@+id/detailUploaderThumbnailView"
android:layout_marginLeft="15dp"
android:layout_marginStart="28dp" />
android:id="@+id/detailUploaderWrapView"
android:layout_marginTop="12dp">
<View
android:background="#000"
<View
android:background="#000"
android:layout_width="match_parent"
android:layout_height="1px" />
<de.hdodenhof.circleimageview.CircleImageView android:id="@+id/detailUploaderThumbnailView"
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
android:layout_width="@dimen/video_item_detail_uploader_image_size"
android:layout_height="@dimen/video_item_detail_uploader_image_size"
android:src="@drawable/buddy"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"/>
<TextView android:id="@+id/detailUploaderView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="@dimen/video_item_detail_uploader_text_size"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Uploader"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/detailUploaderThumbnailView"
android:layout_toEndOf="@+id/detailUploaderThumbnailView"
android:layout_marginLeft="15dp"
android:layout_marginStart="28dp" />
<View
android:background="#000"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="@id/detailUploaderThumbnailView"/>
</RelativeLayout>
<Button
android:layout_marginTop="13dp"
android:id="@+id/channelButton"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_below="@id/detailUploaderThumbnailView"/>
</RelativeLayout>
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground"/>
</FrameLayout>
<RelativeLayout android:id="@+id/detailNextVideoRootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|bottom"
android:layout_below="@+id/detailUploaderWrapView"
android:layout_below="@id/linearLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp">

View File

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<FrameLayout
android:id="@+id/item_main_layout"
android:clickable="true"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
@ -95,4 +98,13 @@
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/item_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@id/detailNextVideoFrame"
android:layout_alignBottom="@id/detailNextVideoFrame"
android:background="?attr/selectableItemBackground"/>
</FrameLayout>