From 5d06e8310d4a29475cf8f8bf7d5f99ca6b95d09d Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Wed, 3 Aug 2016 15:32:25 +0200 Subject: [PATCH] animate item button and made channel layout use recyclerview propper --- .../org/schabi/newpipe/ChannelActivity.java | 151 +++++++----- .../newpipe/StreamInfoItemViewCreator.java | 217 ------------------ .../detail/VideoItemDetailFragment.java | 13 +- .../newpipe/info_list/InfoItemHolder.java | 5 +- .../newpipe/info_list/InfoListAdapter.java | 5 +- app/src/main/res/layout/activity_channel.xml | 17 +- .../res/layout/fragment_videoitem_detail.xml | 87 ++++--- app/src/main/res/layout/video_item.xml | 20 +- 8 files changed, 165 insertions(+), 350 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/StreamInfoItemViewCreator.java diff --git a/app/src/main/java/org/schabi/newpipe/ChannelActivity.java b/app/src/main/java/org/schabi/newpipe/ChannelActivity.java index 332c00e92..80b75e61f 100644 --- a/app/src/main/java/org/schabi/newpipe/ChannelActivity.java +++ b/app/src/main/java/org/schabi/newpipe/ChannelActivity.java @@ -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(); - } - }); - } - - } diff --git a/app/src/main/java/org/schabi/newpipe/StreamInfoItemViewCreator.java b/app/src/main/java/org/schabi/newpipe/StreamInfoItemViewCreator.java deleted file mode 100644 index 1aba6aa1f..000000000 --- a/app/src/main/java/org/schabi/newpipe/StreamInfoItemViewCreator.java +++ /dev/null @@ -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 - * 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 . - */ - -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; - } -} diff --git a/app/src/main/java/org/schabi/newpipe/detail/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/detail/VideoItemDetailFragment.java index 0310113c4..521c6ca02 100644 --- a/app/src/main/java/org/schabi/newpipe/detail/VideoItemDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/detail/VideoItemDetailFragment.java @@ -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); } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemHolder.java index 481f383c0..0e3374dcc 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemHolder.java @@ -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); } } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java index 8c0550b13..fbb220b8d 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java @@ -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 { 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 { 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); diff --git a/app/src/main/res/layout/activity_channel.xml b/app/src/main/res/layout/activity_channel.xml index e1df67b3c..f87553882 100644 --- a/app/src/main/res/layout/activity_channel.xml +++ b/app/src/main/res/layout/activity_channel.xml @@ -87,21 +87,10 @@ android:layout_centerInParent="true" android:indeterminate="true"/> - - - - - + android:scrollbars="vertical"/> diff --git a/app/src/main/res/layout/fragment_videoitem_detail.xml b/app/src/main/res/layout/fragment_videoitem_detail.xml index b155110e3..9cfae29e9 100644 --- a/app/src/main/res/layout/fragment_videoitem_detail.xml +++ b/app/src/main/res/layout/fragment_videoitem_detail.xml @@ -181,55 +181,66 @@ android:text="100" /> - - - + - - - - + android:id="@+id/detailUploaderWrapView" + android:layout_marginTop="12dp"> - + + + + + + + +