i don't know much about java, just started, so i will have difficulties understanding the answers. emli5.
screenshot:
expected output:
in the recyclerview (right), these items are not aligning up like i want them to.
I want that each cell has a fixed size, and maximum number of columns possible in the grid.
spacing b/w each cell (both vertical and horizontal) is equal to (left space) divided by (number of columns minus one). [with no extra space left at start, top, bottom or end]
here is the code:
package com.MyStickersWA.DogeStickers;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
#SuppressWarnings("ALL")
public class StickerPackDetailsActivity extends AddStickerPackActivity {
/**
* Do not change below values of below 3 lines as this is also used by WhatsApp
*/
public static final String EXTRA_STICKER_PACK_ID = "sticker_pack_id";
public static final String EXTRA_STICKER_PACK_AUTHORITY = "sticker_pack_authority";
public static final String EXTRA_STICKER_PACK_NAME = "sticker_pack_name";
public static final String EXTRA_STICKER_PACK_WEBSITE = "sticker_pack_website";
public static final String EXTRA_STICKER_PACK_EMAIL = "sticker_pack_email";
public static final String EXTRA_STICKER_PACK_PRIVACY_POLICY = "sticker_pack_privacy_policy";
public static final String EXTRA_STICKER_PACK_LICENSE_AGREEMENT = "sticker_pack_license_agreement";
public static final String EXTRA_STICKER_PACK_TRAY_ICON = "sticker_pack_tray_icon";
public static final String EXTRA_SHOW_UP_BUTTON = "show_up_button";
public static final String EXTRA_STICKER_PACK_DATA = "sticker_pack";
private RecyclerView recyclerView;
private GridLayoutManager layoutManager;
private StickerPreviewAdapter stickerPreviewAdapter;
private int numColumns;
private View addButton;
private View infoButton;
private View backButton;
private View alreadyAdded;
private StickerPack stickerPack;
private WhiteListCheckAsyncTask whiteListCheckAsyncTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sticker_pack_details);
AdView mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
MobileAds.initialize(this, initializationStatus -> { });
mAdView.loadAd(adRequest);
boolean showUpButton = getIntent().getBooleanExtra(EXTRA_SHOW_UP_BUTTON, false);
stickerPack = getIntent().getParcelableExtra(EXTRA_STICKER_PACK_DATA);
TextView packNameTextView = findViewById(R.id.pack_name);
TextView packPublisherTextView = findViewById(R.id.author);
ImageView packTrayIcon = findViewById(R.id.tray_image);
TextView packSizeTextView = findViewById(R.id.pack_size);
TextView stickersQtyTextView = findViewById(R.id.stickers_qty);
TextView stickersAnimatedView = findViewById(R.id.stickers_animated);
ImageView stickersAnimatedImage = findViewById(R.id.sticker_pack_animation_indicator);
SimpleDraweeView expandedStickerView = findViewById(R.id.sticker_details_expanded_sticker);
addButton = findViewById(R.id.add_to_whatsapp_button);
infoButton = findViewById(R.id.action_info);
backButton = findViewById(R.id.action_back);
alreadyAdded = findViewById(R.id.already_added_button);
layoutManager = new GridLayoutManager(this, 1);
recyclerView = findViewById(R.id.sticker_list);
recyclerView.setLayoutManager(layoutManager);
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(pageLayoutListener);
if (stickerPreviewAdapter == null) {
stickerPreviewAdapter = new StickerPreviewAdapter(getLayoutInflater(), R.drawable.sticker_error, getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size), getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_padding), stickerPack, expandedStickerView);
recyclerView.setAdapter(stickerPreviewAdapter);
}
packNameTextView.setText(stickerPack.name);
packPublisherTextView.setText(stickerPack.publisher);
packTrayIcon.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile));
packSizeTextView.setText(Formatter.formatShortFileSize(this, stickerPack.getTotalSize()));
stickersQtyTextView.setText(stickerPack.getTotalQty() + "");
addButton.setOnClickListener(v -> addStickerPackToWhatsApp(stickerPack.identifier, stickerPack.name));
infoButton.setOnClickListener(v -> onOptionsItemSelected());
backButton.setOnClickListener(v -> finish());
if (stickerPack.animatedStickerPack) {
Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.animated_indicator_vector);
stickersAnimatedImage.setImageURI(animatedIcon);
stickersAnimatedView.setText("Animated");
} else {
Uri animatedIcon = Uri.parse("android.resource://" + getPackageName() + "/"+R.drawable.static_indicator_vector);
stickersAnimatedImage.setImageURI(animatedIcon);
stickersAnimatedView.setText("Static");
}
}
private void launchInfoActivity(String publisherWebsite, String publisherEmail, String privacyPolicyWebsite, String licenseAgreementWebsite, String trayIconUriString) {
Intent intent = new Intent(StickerPackDetailsActivity.this, StickerPackInfoActivity.class);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_ID, stickerPack.identifier);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_WEBSITE, publisherWebsite);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_EMAIL, publisherEmail);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_PRIVACY_POLICY, privacyPolicyWebsite);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_LICENSE_AGREEMENT, licenseAgreementWebsite);
intent.putExtra(StickerPackDetailsActivity.EXTRA_STICKER_PACK_TRAY_ICON, trayIconUriString);
startActivity(intent);
}
public boolean onOptionsItemSelected() {
if (stickerPack != null) {
Uri trayIconUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.trayImageFile);
launchInfoActivity(stickerPack.publisherWebsite, stickerPack.publisherEmail, stickerPack.privacyPolicyWebsite, stickerPack.licenseAgreementWebsite, trayIconUri.toString());
return true;
}
return false;
}
private final ViewTreeObserver.OnGlobalLayoutListener pageLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int imgSize = recyclerView.getContext().getResources().getDimensionPixelSize(R.dimen.sticker_pack_details_image_size);
int recyclerViewWidth = recyclerView.getWidth();
int numColumns = recyclerViewWidth / imgSize;
int colSpacing = (recyclerViewWidth - (numColumns * imgSize)) / (numColumns - 1);
// int colSpacing = recyclerView.getWidth() - imgSize * numColumns;
setNumColumns(numColumns, colSpacing);
}
};
#SuppressLint("NotifyDataSetChanged")
private void setNumColumns(int numColumns, int colSpacing) {
if (this.numColumns != numColumns) {
// recyclerView.addItemDecoration(new GridSpacingItemDecoration(4, 2, 2));
layoutManager.setSpanCount(numColumns);
recyclerView.setLayoutManager(layoutManager);
this.numColumns = numColumns;
if (stickerPreviewAdapter != null) {
stickerPreviewAdapter.notifyDataSetChanged();
}
}
}
#Override
protected void onResume() {
super.onResume();
whiteListCheckAsyncTask = new WhiteListCheckAsyncTask(this);
whiteListCheckAsyncTask.execute(stickerPack);
}
#Override
protected void onPause() {
super.onPause();
if (whiteListCheckAsyncTask != null && !whiteListCheckAsyncTask.isCancelled()) {
whiteListCheckAsyncTask.cancel(true);
}
}
private void updateAddUI(Boolean isWhitelisted) {
if (isWhitelisted) {
addButton.setVisibility(View.GONE);
alreadyAdded.setVisibility(View.VISIBLE);
} else {
addButton.setVisibility(View.VISIBLE);
alreadyAdded.setVisibility(View.GONE);
}
}
static class WhiteListCheckAsyncTask extends AsyncTask<StickerPack, Void, Boolean> {
private final WeakReference<StickerPackDetailsActivity> stickerPackDetailsActivityWeakReference;
WhiteListCheckAsyncTask(StickerPackDetailsActivity stickerPackListActivity) {
this.stickerPackDetailsActivityWeakReference = new WeakReference<>(stickerPackListActivity);
}
#Override
protected final Boolean doInBackground(StickerPack... stickerPacks) {
StickerPack stickerPack = stickerPacks[0];
final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
if (stickerPackDetailsActivity == null) {
return false;
}
return WhitelistCheck.isWhitelisted(stickerPackDetailsActivity, stickerPack.identifier);
}
#Override
protected void onPostExecute(Boolean isWhitelisted) {
final StickerPackDetailsActivity stickerPackDetailsActivity = stickerPackDetailsActivityWeakReference.get();
if (stickerPackDetailsActivity != null) {
stickerPackDetailsActivity.updateAddUI(isWhitelisted);
}
}
}
}
/*
* Copyright (c) WhatsApp Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.MyStickersWA.DogeStickers;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
public class StickerPreviewAdapter extends RecyclerView.Adapter<StickerPreviewViewHolder> {
private static final float COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA = 1f;
private static final float EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA = 0.2f;
#NonNull
private final StickerPack stickerPack;
private final int cellSize;
private final int cellLimit;
private final int cellPadding;
private final int errorResource;
private final SimpleDraweeView expandedStickerPreview;
private final LayoutInflater layoutInflater;
private RecyclerView recyclerView;
private View clickedStickerPreview;
float expandedViewLeftX;
float expandedViewTopY;
StickerPreviewAdapter(
#NonNull final LayoutInflater layoutInflater,
final int errorResource,
final int cellSize,
final int cellPadding,
#NonNull final StickerPack stickerPack,
final SimpleDraweeView expandedStickerView) {
this.cellSize = cellSize;
this.cellPadding = cellPadding;
this.cellLimit = 0;
this.layoutInflater = layoutInflater;
this.errorResource = errorResource;
this.stickerPack = stickerPack;
this.expandedStickerPreview = expandedStickerView;
}
#NonNull
#Override
public StickerPreviewViewHolder onCreateViewHolder(#NonNull final ViewGroup viewGroup, final int i) {
View itemView = layoutInflater.inflate(R.layout.sticker_image_item, viewGroup, false);
StickerPreviewViewHolder vh = new StickerPreviewViewHolder(itemView);
ViewGroup.LayoutParams layoutParams = vh.stickerPreviewView.getLayoutParams();
layoutParams.height = cellSize;
layoutParams.width = cellSize;
vh.stickerPreviewView.setLayoutParams(layoutParams);
vh.stickerPreviewView.setPadding(cellPadding, cellPadding, cellPadding, cellPadding);
return vh;
}
#Override
public void onBindViewHolder(#NonNull final StickerPreviewViewHolder stickerPreviewViewHolder, final int i) {
stickerPreviewViewHolder.stickerPreviewView.setImageResource(errorResource);
stickerPreviewViewHolder.stickerPreviewView.setImageURI(StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(i).imageFileName));
stickerPreviewViewHolder.stickerPreviewView.setOnClickListener(v -> expandPreview(i, stickerPreviewViewHolder.stickerPreviewView));
}
#Override
public void onAttachedToRecyclerView(#NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
recyclerView.addOnScrollListener(hideExpandedViewScrollListener);
}
#Override
public void onDetachedFromRecyclerView(#NonNull RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
recyclerView.removeOnScrollListener(hideExpandedViewScrollListener);
this.recyclerView = null;
}
private final RecyclerView.OnScrollListener hideExpandedViewScrollListener =
new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dx != 0 || dy != 0) {
hideExpandedStickerPreview();
}
}
};
private void positionExpandedStickerPreview(int selectedPosition) {
if (expandedStickerPreview != null) {
// Calculate the view's center (x, y), then use expandedStickerPreview's height and
// width to
// figure out what where to position it.
final ViewGroup.MarginLayoutParams recyclerViewLayoutParams =
((ViewGroup.MarginLayoutParams) recyclerView.getLayoutParams());
final int recyclerViewLeftMargin = recyclerViewLayoutParams.leftMargin;
final int recyclerViewRightMargin = recyclerViewLayoutParams.rightMargin;
final int recyclerViewWidth = recyclerView.getWidth();
final int recyclerViewHeight = recyclerView.getHeight();
final StickerPreviewViewHolder clickedViewHolder =
(StickerPreviewViewHolder)
recyclerView.findViewHolderForAdapterPosition(selectedPosition);
if (clickedViewHolder == null) {
hideExpandedStickerPreview();
return;
}
clickedStickerPreview = clickedViewHolder.itemView;
final float clickedViewCenterX =
clickedStickerPreview.getX()
+ recyclerViewLeftMargin
+ clickedStickerPreview.getWidth() / 2f;
final float clickedViewCenterY =
clickedStickerPreview.getY() + clickedStickerPreview.getHeight() / 2f;
expandedViewLeftX = clickedViewCenterX - expandedStickerPreview.getWidth() / 2f;
expandedViewTopY = clickedViewCenterY - expandedStickerPreview.getHeight() / 2f;
// If the new x or y positions are negative, anchor them to 0 to avoid clipping
// the left side of the device and the top of the recycler view.
expandedViewLeftX = Math.max(expandedViewLeftX, 0);
expandedViewTopY = Math.max(expandedViewTopY, 0);
// If the bottom or right sides are clipped, we need to move the top left positions
// so that those sides are no longer clipped.
final float adjustmentX =
Math.max(
expandedViewLeftX
+ expandedStickerPreview.getWidth()
- recyclerViewWidth
- recyclerViewRightMargin,
0);
final float adjustmentY =
Math.max(expandedViewTopY + expandedStickerPreview.getHeight() - recyclerViewHeight, 0);
expandedViewLeftX -= adjustmentX;
expandedViewTopY -= adjustmentY;
expandedStickerPreview.setX(expandedViewLeftX);
expandedStickerPreview.setY(expandedViewTopY);
}
}
private void expandPreview(int position, View clickedStickerPreview) {
if (isStickerPreviewExpanded()) {
hideExpandedStickerPreview();
return;
}
this.clickedStickerPreview = clickedStickerPreview;
if (expandedStickerPreview != null) {
positionExpandedStickerPreview(position);
final Uri stickerAssetUri = StickerPackLoader.getStickerAssetUri(stickerPack.identifier, stickerPack.getStickers().get(position).imageFileName);
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(stickerAssetUri)
.setAutoPlayAnimations(true)
.build();
expandedStickerPreview.setImageResource(errorResource);
expandedStickerPreview.setController(controller);
expandedStickerPreview.setVisibility(View.VISIBLE);
recyclerView.setAlpha(EXPANDED_STICKER_PREVIEW_BACKGROUND_ALPHA);
expandedStickerPreview.setOnClickListener(v -> hideExpandedStickerPreview());
}
}
public void hideExpandedStickerPreview() {
if (isStickerPreviewExpanded() && expandedStickerPreview != null) {
clickedStickerPreview.setVisibility(View.VISIBLE);
expandedStickerPreview.setVisibility(View.INVISIBLE);
recyclerView.setAlpha(COLLAPSED_STICKER_PREVIEW_BACKGROUND_ALPHA);
}
}
private boolean isStickerPreviewExpanded() {
return expandedStickerPreview != null && expandedStickerPreview.getVisibility() == View.VISIBLE;
}
#Override
public int getItemCount() {
int numberOfPreviewImagesInPack;
numberOfPreviewImagesInPack = stickerPack.getStickers().size();
if (cellLimit > 0) {
return Math.min(numberOfPreviewImagesInPack, cellLimit);
}
return numberOfPreviewImagesInPack;
}
}
thanks in advance
You need to create a custom item decoration by extending RecyclerView.ItemDecoration. You can do something like this:
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private final int numberOfColumns;
private final int spacing;
private final boolean addSpacingToPerimeter;
public GridSpacingItemDecoration(int numberOfColumns, int spacing, boolean addSpacingToPerimeter) {
this.numberOfColumns = numberOfColumns;
this.spacing = spacing;
this.addSpacingToPerimeter = addSpacingToPerimeter;
}
#Override
public void getItemOffsets(#NonNull Rect outRect, #NonNull View view, RecyclerView parent, #NonNull RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % numberOfColumns; // item column
if (addSpacingToPerimeter) {
outRect.left = spacing - column * spacing / numberOfColumns;
outRect.right = (column + 1) * spacing / numberOfColumns;
if (position < numberOfColumns) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / numberOfColumns;
outRect.right = spacing - (column + 1) * spacing / numberOfColumns;
if (position >= numberOfColumns) {
outRect.top = spacing; // item top
}
}
}
}
and then use it like this
int numberOfColumns = 3; // 3 columns
int spacing = 50; // 50px
boolean addSpacingToPerimeter = false;
recyclerView.addItemDecoration(new GridSpacingItemDecoration(numberOfColumns, spacing, addSpacingToPerimeter))
The GridSpacingItemDecoration class takes as a parameter the number of columns, the spacing in pixel and a boolean value that specifies whether you want spacing to be added to the list's perimeter as well. This boolean if set to true will add the given spacing as a margin not only between the grid adapter's items, but also between the items and the whole recyclerView.
Keep in mind that spacing is in pixels. So if you want to use dp instead, you can convert dp to px using
Math.round(dpValue * getResources().getDisplayMetrics().density))
It seems like every item has right padding.
You should use addItemDecoration on your RecyclerView instead.
Or use this: https://github.com/grzegorzojdana/SpacingItemDecoration
Related
I am using PullToRefreshListView to provide data reload when pulling the listview.
But my problem is that after refreshing, the layout leaves a space on top of the listview. See the image below:
I want to remove the space on top. I tried setting the view to View.GONE but it still leaves a small space in it.
Here's the code for the PullToRefreshListView.java:
package com.markupartist.android.widget;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
public class PullToRefreshListView extends ListView implements OnScrollListener {
private static final int TAP_TO_REFRESH = 1;
private static final int PULL_TO_REFRESH = 2;
private static final int RELEASE_TO_REFRESH = 3;
private static final int REFRESHING = 4;
private static final String TAG = "PullToRefreshListView";
private OnRefreshListener mOnRefreshListener;
/**
* Listener that will receive notifications every time the list scrolls.
*/
private OnScrollListener mOnScrollListener;
private LayoutInflater mInflater;
private RelativeLayout mRefreshView;
private TextView mRefreshViewText;
private ImageView mRefreshViewImage;
private ProgressBar mRefreshViewProgress;
private TextView mRefreshViewLastUpdated;
private int mCurrentScrollState;
private int mRefreshState;
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
private int mRefreshViewHeight;
private int mRefreshOriginalTopPadding;
private int mLastMotionY;
private boolean mBounceHack;
public PullToRefreshListView(Context context) {
super(context);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
// Load all of the animations we need in code rather than through XML
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setInterpolator(new LinearInterpolator());
mFlipAnimation.setDuration(250);
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration(250);
mReverseFlipAnimation.setFillAfter(true);
mInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mRefreshView = (RelativeLayout) mInflater.inflate(
R.layout.pull_to_refresh_header, this, false);
mRefreshViewText =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
mRefreshViewImage =
(ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
mRefreshViewProgress =
(ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
mRefreshViewLastUpdated =
(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);
mRefreshViewImage.setMinimumHeight(50);
mRefreshView.setOnClickListener(new OnClickRefreshListener());
mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();
mRefreshState = TAP_TO_REFRESH;
addHeaderView(mRefreshView);
super.setOnScrollListener(this);
measureView(mRefreshView);
mRefreshViewHeight = mRefreshView.getMeasuredHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelection(1);
}
#Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
setSelection(1);
}
/**
* Set the listener that will receive notifications every time the list
* scrolls.
*
* #param l The scroll listener.
*/
#Override
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener = l;
}
/**
* Register a callback to be invoked when this list should be refreshed.
*
* #param onRefreshListener The callback to run.
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
mOnRefreshListener = onRefreshListener;
}
/**
* Set a text to represent when the list was last updated.
* #param lastUpdated Last updated at.
*/
public void setLastUpdated(CharSequence lastUpdated) {
if (lastUpdated != null) {
mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
mRefreshViewLastUpdated.setText(lastUpdated);
} else {
mRefreshViewLastUpdated.setVisibility(View.GONE);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int y = (int) event.getY();
mBounceHack = false;
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
if ((mRefreshView.getBottom() >= mRefreshViewHeight
|| mRefreshView.getTop() >= 0)
&& mRefreshState == RELEASE_TO_REFRESH) {
// Initiate the refresh
mRefreshState = REFRESHING;
prepareForRefresh();
onRefresh();
} else if (mRefreshView.getBottom() < mRefreshViewHeight
|| mRefreshView.getTop() <= 0) {
// Abort refresh and scroll down below the refresh view
resetHeader();
setSelection(1);
}
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
applyHeaderPadding(event);
break;
}
return super.onTouchEvent(event);
}
private void applyHeaderPadding(MotionEvent ev) {
// getHistorySize has been available since API 1
int pointerCount = ev.getHistorySize();
for (int p = 0; p < pointerCount; p++) {
if (mRefreshState == RELEASE_TO_REFRESH) {
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
int historicalY = (int) ev.getHistoricalY(p);
// Calculate the padding to apply, we divide by 1.7 to
// simulate a more resistant effect during pull.
int topPadding = (int) (((historicalY - mLastMotionY)
- mRefreshViewHeight) / 1.7);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
topPadding,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
}
}
/**
* Sets the header padding back to original size.
*/
private void resetHeaderPadding() {
Log.i("top padding", "" + mRefreshOriginalTopPadding);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
0,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
/**
* Resets the header to the original state.
*/
private void resetHeader() {
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshState = TAP_TO_REFRESH;
resetHeaderPadding();
// Set refresh view text to the pull label
//mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
//mRefreshViewText.setVisibility(View.GONE);
// Replace refresh drawable with arrow drawable
mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
// Clear the full rotation animation
mRefreshViewImage.clearAnimation();
// Hide progress bar and arrow.
mRefreshViewImage.setVisibility(View.GONE);
mRefreshViewProgress.setVisibility(View.GONE);
//this.setSelectionAfterHeaderView();
}
}
private void measureView(View child) {
ViewGroup.LayoutParams p = child.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0,
0 + 0, p.width);
int lpHeight = p.height;
int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// When the refresh view is completely visible, change the text to say
// "Release to refresh..." and flip the arrow drawable.
if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
&& mRefreshState != REFRESHING) {
if (firstVisibleItem == 0) {
mRefreshViewImage.setVisibility(View.VISIBLE);
if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20
|| mRefreshView.getTop() >= 0)
&& mRefreshState != RELEASE_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mFlipAnimation);
mRefreshState = RELEASE_TO_REFRESH;
} else if (mRefreshView.getBottom() < mRefreshViewHeight + 20
&& mRefreshState != PULL_TO_REFRESH) {
mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mReverseFlipAnimation);
}
mRefreshState = PULL_TO_REFRESH;
}
} else {
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
}
} else if (mCurrentScrollState == SCROLL_STATE_FLING
&& firstVisibleItem == 0
&& mRefreshState != REFRESHING) {
Log.i("I am here", "");
setSelection(1);
mBounceHack = true;
} else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {
setSelection(1);
}
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
if (mCurrentScrollState == SCROLL_STATE_IDLE) {
mBounceHack = false;
}
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
public void prepareForRefresh() {
resetHeaderPadding();
mRefreshViewImage.setVisibility(View.GONE);
// We need this hack, otherwise it will keep the previous drawable.
mRefreshViewImage.setImageDrawable(null);
mRefreshViewProgress.setVisibility(View.VISIBLE);
// Set refresh view text to the refreshing label
mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
mRefreshState = REFRESHING;
}
public void onRefresh() {
Log.d(TAG, "onRefresh");
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
}
}
/**
* Resets the list to a normal state after a refresh.
* #param lastUpdated Last updated at.
*/
public void onRefreshComplete(CharSequence lastUpdated) {
setLastUpdated(lastUpdated);
onRefreshComplete();
}
/**
* Resets the list to a normal state after a refresh.
*/
public void onRefreshComplete() {
Log.d(TAG, "onRefreshComplete");
resetHeader();
// If refresh view is visible when loading completes, scroll down to
// the next item.
if (getFirstVisiblePosition() == 0) {
invalidateViews();
setSelection(1);
}
resetHeader();
}
/**
* Invoked when the refresh view is clicked on. This is mainly used when
* there's only a few items in the list and it's not possible to drag the
* list.
*/
private class OnClickRefreshListener implements OnClickListener {
#Override
public void onClick(View v) {
if (mRefreshState != REFRESHING) {
prepareForRefresh();
onRefresh();
}
}
}
/**
* Interface definition for a callback to be invoked when list should be
* refreshed.
*/
public interface OnRefreshListener {
/**
* Called when the list should be refreshed.
* <p>
* A call to {#link PullToRefreshListView #onRefreshComplete()} is
* expected to indicate that the refresh has completed.
*/
public void onRefresh();
}
}
I would suggest you to Just disable listview onrefresh listener and
use android.support.v4.widget.SwipeRefreshLayout instead of pull to refresh listview . It is very easy to use.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refreshLater"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
***Place Your listview here***
</android.support.v4.widget.SwipeRefreshLayout >
you can set refresh listener on it like this:
public SwipeRefreshLayout swipeRefreshLayout;
swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.refreshLater);
swipeRefreshLayout.setOnRefreshListener(this);
you can do needed code in the below override method:
#Override
public void onRefresh()
{
swipeRefreshLayout.setRefreshing(false);
}
I am adding some EditTexts dynamically, when a button is clicked, the information is entered and displayed on a text View, I need to make invisible all the EditText Views, the problem that I am facing is that only the last EditText added goes invisible. I tried to set a tag to set the EditText invisible but it is not working Am I missing something?
Any assistance with this would be appreciated.
import java.util.ArrayList;
import java.util.List;
import com.juancho.workingout.R;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.InputFilter;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class TEST extends Fragment {
// Add EditText Dynamically
RelativeLayout containerLayout;
static int exercisesViews = 0; // initial value
public int totalExercisesViews = 15;
Context context;
private int counterExeNumber = 1;
private int margingTopEditTextInitial = 120; // default position
private int margingTopNumberAdd = 130;
private List<EditText> editTextListName = new ArrayList<>();
EditText EditTextName;
String nameResultCardio, nameResult1, nameResult2, nameResult3;
int myTagValueCardio;
int myTagValueYesCardioExe2, myTagValueYesCardioExe3;
boolean cardioViewEnable = false;
boolean exe2IfCardioViewEnable = false;
boolean exe3IfCardioViewEnable = false;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
final View ViewCalendarEditNotesInfo = inflater.inflate(R.layout.logs_add_notes, null);
exercisesViews = 0; // Reset
containerLayout = (RelativeLayout) ViewCalendarEditNotesInfo.findViewById(R.id.layout1);
LogsAddNotes.isExercise1Enable = true;
LogsAddNotes.isExercise2Enable = true;
LogsAddNotes.isExercise3Enable = true;
final Button btnSave = (Button) ViewCalendarEditNotesInfo.findViewById(R.id.btnSave);
btnSave.setVisibility(View.VISIBLE);
if (LogsAddNotes.isExercise1Enable == true) {
// Set Views
editTextName(exercisesViews);
myTagValueCardio = (int) EditTextName.getTag();
cardioViewEnable = true;
}
// --------------------------------------------------------------------------------------------------------------------------------------------
if (LogsAddNotes.isExercise2Enable == true) {
exercisesViews++;
counterExeNumber++;
margingTopEditTextInitial = margingTopEditTextInitial + margingTopNumberAdd;
// Set Views
editTextName(exercisesViews);
// Get information entered
nameResult2 = EditTextName.getText().toString();
myTagValueYesCardioExe2 = (int) EditTextName.getTag();
exe2IfCardioViewEnable = true;
}
// --------------------------------------------------------------------------------------------------------------------------------------------
if (LogsAddNotes.isExercise3Enable == true) {
exercisesViews++;
counterExeNumber++;
margingTopEditTextInitial = margingTopEditTextInitial + margingTopNumberAdd;
// Set Views
editTextName(exercisesViews);
// Get information entered
nameResult3 = EditTextName.getText().toString();
myTagValueYesCardioExe3 = (int) EditTextName.getTag();
exe3IfCardioViewEnable = true;
}
btnSave.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int index = 0;
while (index < editTextListName.size()) {
// --------------------------------------------------------------------------------------------------
if (cardioViewEnable == true && index == 0) {
nameResultCardio = editTextListName.get(index).getText().toString();
if (myTagValueCardio == index) {
// tToast("B1");
EditTextName.setVisibility(View.INVISIBLE);
}
}
// --------------------------------------------------------------------------------------------------
if (exe2IfCardioViewEnable == true && index == 1) {
nameResult2 = editTextListName.get(index).getText().toString();
if (myTagValueYesCardioExe2 == index) {
// tToast("B2");
EditTextName.setVisibility(View.INVISIBLE);
}
}
// --------------------------------------------------------------------------------------------------
if (exe3IfCardioViewEnable == true && index == 2) {
nameResult3 = editTextListName.get(index).getText().toString();
if (myTagValueYesCardioExe3 == index) {
// tToast(" B3");
EditTextName.setVisibility(View.INVISIBLE);
}
}
// more exercises HERE
index++;
} // end while loop
}// end Click
});
return ViewCalendarEditNotesInfo;
}// end Main
// -----------------------------------------------------------------------------------------
private EditText editTextName(int _intID) {
EditTextName = new EditText(getActivity());
EditTextName.setId(_intID);
EditTextName.setHint("Name");
// CharSequence hint = "\u200F" + editText.getHint();
// editText.setHint(hint);
// Maximum input chars allow
int maxLength = 10;
// Allow only Letters
EditTextName.setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxLength), new InputFilter() {
public CharSequence filter(CharSequence src, int start, int end, Spanned dst, int dstart, int dend) {
if (src.equals("")) { // for backspace
return src;
}
if (src.toString().matches("[a-zA-Z ]+")) {
return src;
}
return "";
}
} });
editTextListName.add(EditTextName);
containerLayout.addView(EditTextName);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) EditTextName.getLayoutParams();
layoutParams.width = RelativeLayout.LayoutParams.MATCH_PARENT;
layoutParams.setMargins(300, margingTopEditTextInitial, 750, 0);
// RelativeLayout.LayoutParams()
EditTextName.setLayoutParams(layoutParams);
// if you want to identify the created editTexts, set a tag, like below
// EditTextName[i].setTag("EditText" + editText.getId());
EditTextName.setTag(_intID);
// tToast("THE TAG= " + _intID);
return EditTextName;
}
}
I am using PagerSlidingTabStrip in an Android project.
When I swipe through the tabs, it is working correctly.
However, when I click on a tab, the tab does not change.
Here is the activity XML:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<au.edu.me.meandroidapplication.view.thirdparty.PagerSlidingTabStrip
android:id="#+id/progress_pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="48dip"
app:pstsShouldExpand="true"
app:pstsIndicatorColor="#color/meTabIndicator"
app:pstsDividerColor="#color/meTabSeparator"
android:background="#color/meTabBackground" />
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/progressViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="au.edu.me.meandroidapplication.view.activity.MyProgressActivity" />
</RelativeLayout>
Here is my code in onCreate():
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_progress);
this.viewPager = (ViewPager)this.findViewById(R.id.progressViewPager);
this.pagerAdapter = new MyProgressFragmentPagerAdapter(this.getSupportFragmentManager());
this.viewPager.setAdapter(this.pagerAdapter);
PagerSlidingTabStrip pagerTabStrip = (PagerSlidingTabStrip)this.findViewById(R.id.progress_pager_tab_strip);
pagerTabStrip.setViewPager(this.viewPager);
pagerTabStrip.setTextColorResource(R.color.meTabText);
}
Any advice on how to click the buttons to also change the tabs would be greatly appreciated!
Edit: yes the importing is from this project and not any other one. here is the code for PagerSlidingTabStrip
package au.edu.me.meandroidapplication.view.thirdparty;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.Locale;
import au.edu.me.meandroidapplication.R;
public class PagerSlidingTabStrip extends HorizontalScrollView {
public interface IconTabProvider {
public int getPageIconResId(int position);
}
// #formatter:off
private static final int[] ATTRS = new int[] {
android.R.attr.textSize,
android.R.attr.textColor
};
// #formatter:on
private LinearLayout.LayoutParams defaultTabLayoutParams;
private LinearLayout.LayoutParams expandedTabLayoutParams;
private final PageListener pageListener = new PageListener();
public OnPageChangeListener delegatePageListener;
private LinearLayout tabsContainer;
private ViewPager pager;
private int tabCount;
private int currentPosition = 0;
private float currentPositionOffset = 0f;
private Paint rectPaint;
private Paint dividerPaint;
private int indicatorColor = 0xFF666666;
private int underlineColor = 0x1A000000;
private int dividerColor = 0x1A000000;
private boolean shouldExpand = false;
private boolean textAllCaps = true;
private int scrollOffset = 52;
private int indicatorHeight = 8;
private int underlineHeight = 2;
private int dividerPadding = 12;
private int tabPadding = 24;
private int dividerWidth = 1;
private int tabTextSize = 12;
private int tabTextColor = 0xFF666666;
private Typeface tabTypeface = null;
private int tabTypefaceStyle = Typeface.BOLD;
private int lastScrollX = 0;
private int tabBackgroundResId = -1; // ### REMOVED
private Locale locale;
public PagerSlidingTabStrip(Context context) {
this(context, null);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PagerSlidingTabStrip(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setFillViewport(true);
setWillNotDraw(false);
tabsContainer = new LinearLayout(context);
tabsContainer.setOrientation(LinearLayout.HORIZONTAL);
tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(tabsContainer);
DisplayMetrics dm = getResources().getDisplayMetrics();
scrollOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm);
indicatorHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm);
underlineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm);
dividerPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm);
tabPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm);
dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm);
tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);
// get system attrs (android:textSize and android:textColor)
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
tabTextColor = a.getColor(1, tabTextColor);
a.recycle();
// get custom attrs
a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip);
indicatorColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsIndicatorColor, indicatorColor);
underlineColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsUnderlineColor, underlineColor);
dividerColor = a.getColor(R.styleable.PagerSlidingTabStrip_pstsDividerColor, dividerColor);
indicatorHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsIndicatorHeight, indicatorHeight);
underlineHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsUnderlineHeight, underlineHeight);
dividerPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsDividerPadding, dividerPadding);
tabPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsTabPaddingLeftRight, tabPadding);
tabBackgroundResId = a.getResourceId(R.styleable.PagerSlidingTabStrip_pstsTabBackground, tabBackgroundResId);
shouldExpand = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsShouldExpand, shouldExpand);
scrollOffset = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_pstsScrollOffset, scrollOffset);
textAllCaps = a.getBoolean(R.styleable.PagerSlidingTabStrip_pstsTextAllCaps, textAllCaps);
a.recycle();
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
dividerPaint = new Paint();
dividerPaint.setAntiAlias(true);
dividerPaint.setStrokeWidth(dividerWidth);
defaultTabLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
expandedTabLayoutParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);
if (locale == null) {
locale = getResources().getConfiguration().locale;
}
}
public void setViewPager(ViewPager pager) {
this.pager = pager;
if (pager.getAdapter() == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
pager.setOnPageChangeListener(pageListener);
notifyDataSetChanged();
}
public void setOnPageChangeListener(OnPageChangeListener listener) {
this.delegatePageListener = listener;
}
public void notifyDataSetChanged() {
tabsContainer.removeAllViews();
tabCount = pager.getAdapter().getCount();
for (int i = 0; i < tabCount; i++) {
if (pager.getAdapter() instanceof IconTabProvider) {
addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconResId(i));
} else {
addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
}
}
updateTabStyles();
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
currentPosition = pager.getCurrentItem();
scrollToChild(currentPosition, 0);
}
});
}
private void addTextTab(final int position, String title) {
TextView tab = new TextView(getContext());
tab.setText(title);
tab.setGravity(Gravity.CENTER);
tab.setSingleLine();
addTab(position, tab);
}
private void addIconTab(final int position, int resId) {
ImageButton tab = new ImageButton(getContext());
tab.setImageResource(resId);
addTab(position, tab);
}
private void addTab(final int position, View tab) {
tab.setFocusable(true);
tab.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
pager.setCurrentItem(position);
}
});
tab.setPadding(tabPadding, 0, tabPadding, 0);
tabsContainer.addView(tab, position, shouldExpand ? expandedTabLayoutParams : defaultTabLayoutParams);
}
private void updateTabStyles() {
for (int i = 0; i < tabCount; i++) {
View v = tabsContainer.getChildAt(i);
// v.setBackgroundResource(tabBackgroundResId); // ### removed
if (v instanceof TextView) {
TextView tab = (TextView) v;
tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
tab.setTypeface(tabTypeface, tabTypefaceStyle);
tab.setTextColor(tabTextColor);
// setAllCaps() is only available from API 14, so the upper case is made manually if we are on a
// pre-ICS-build
if (textAllCaps) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
tab.setAllCaps(true);
} else {
tab.setText(tab.getText().toString().toUpperCase(locale));
}
}
}
}
}
private void scrollToChild(int position, int offset) {
if (tabCount == 0) {
return;
}
int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;
if (position > 0 || offset > 0) {
newScrollX -= scrollOffset;
}
if (newScrollX != lastScrollX) {
lastScrollX = newScrollX;
scrollTo(newScrollX, 0);
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode() || tabCount == 0) {
return;
}
final int height = getHeight();
// draw indicator line
rectPaint.setColor(indicatorColor);
// default: line below current tab
View currentTab = tabsContainer.getChildAt(currentPosition);
float lineLeft = currentTab.getLeft();
float lineRight = currentTab.getRight();
// if there is an offset, start interpolating left and right coordinates between current and next tab
if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {
View nextTab = tabsContainer.getChildAt(currentPosition + 1);
final float nextTabLeft = nextTab.getLeft();
final float nextTabRight = nextTab.getRight();
lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft);
lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight);
}
canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint);
// draw underline
rectPaint.setColor(underlineColor);
canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint);
// draw divider
dividerPaint.setColor(dividerColor);
for (int i = 0; i < tabCount - 1; i++) {
View tab = tabsContainer.getChildAt(i);
canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint);
}
}
private class PageListener implements OnPageChangeListener {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
currentPosition = position;
currentPositionOffset = positionOffset;
scrollToChild(position, (int) (positionOffset * tabsContainer.getChildAt(position).getWidth()));
invalidate();
if (delegatePageListener != null) {
delegatePageListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
scrollToChild(pager.getCurrentItem(), 0);
}
if (delegatePageListener != null) {
delegatePageListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (delegatePageListener != null) {
delegatePageListener.onPageSelected(position);
}
}
}
public void setIndicatorColor(int indicatorColor) {
this.indicatorColor = indicatorColor;
invalidate();
}
public void setIndicatorColorResource(int resId) {
this.indicatorColor = getResources().getColor(resId);
invalidate();
}
public int getIndicatorColor() {
return this.indicatorColor;
}
public void setIndicatorHeight(int indicatorLineHeightPx) {
this.indicatorHeight = indicatorLineHeightPx;
invalidate();
}
public int getIndicatorHeight() {
return indicatorHeight;
}
public void setUnderlineColor(int underlineColor) {
this.underlineColor = underlineColor;
invalidate();
}
public void setUnderlineColorResource(int resId) {
this.underlineColor = getResources().getColor(resId);
invalidate();
}
public int getUnderlineColor() {
return underlineColor;
}
public void setDividerColor(int dividerColor) {
this.dividerColor = dividerColor;
invalidate();
}
public void setDividerColorResource(int resId) {
this.dividerColor = getResources().getColor(resId);
invalidate();
}
public int getDividerColor() {
return dividerColor;
}
public void setUnderlineHeight(int underlineHeightPx) {
this.underlineHeight = underlineHeightPx;
invalidate();
}
public int getUnderlineHeight() {
return underlineHeight;
}
public void setDividerPadding(int dividerPaddingPx) {
this.dividerPadding = dividerPaddingPx;
invalidate();
}
public int getDividerPadding() {
return dividerPadding;
}
public void setScrollOffset(int scrollOffsetPx) {
this.scrollOffset = scrollOffsetPx;
invalidate();
}
public int getScrollOffset() {
return scrollOffset;
}
public void setShouldExpand(boolean shouldExpand) {
this.shouldExpand = shouldExpand;
requestLayout();
}
public boolean getShouldExpand() {
return shouldExpand;
}
public boolean isTextAllCaps() {
return textAllCaps;
}
public void setAllCaps(boolean textAllCaps) {
this.textAllCaps = textAllCaps;
}
public void setTextSize(int textSizePx) {
this.tabTextSize = textSizePx;
updateTabStyles();
}
public int getTextSize() {
return tabTextSize;
}
public void setTextColor(int textColor) {
this.tabTextColor = textColor;
updateTabStyles();
}
public void setTextColorResource(int resId) {
this.tabTextColor = getResources().getColor(resId);
updateTabStyles();
}
public int getTextColor() {
return tabTextColor;
}
public void setTypeface(Typeface typeface, int style) {
this.tabTypeface = typeface;
this.tabTypefaceStyle = style;
updateTabStyles();
}
public void setTabBackground(int resId) {
this.tabBackgroundResId = resId;
}
public int getTabBackground() {
return tabBackgroundResId;
}
public void setTabPaddingLeftRight(int paddingPx) {
this.tabPadding = paddingPx;
updateTabStyles();
}
public int getTabPaddingLeftRight() {
return tabPadding;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
#Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPosition;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPosition = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPosition);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
I am trying to implement tabs into my application and I have added the SlidingTabLayout.java and SlidingTabStrip.java from Google. I also made sure to add the setDistributeEvenly method within the SlidingTabLayout class.
My problem is coming from the R.attr.colorForeground. I am getting the error 'Cannot resolve sysmbol 'colorForeground'.
Here is the the two classes for which these are made for the tabs.
class SlidingTabStrip extends LinearLayout {
private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0;
private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3;
private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;
private final int mBottomBorderThickness;
private final Paint mBottomBorderPaint;
private final int mSelectedIndicatorThickness;
private final Paint mSelectedIndicatorPaint;
private final int mDefaultBottomBorderColor;
private final SimpleTabColorizer mDefaultTabColorizer;
private int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout.TabColorizer mCustomTabColorizer;
SlidingTabStrip(Context context) {
this(context, null);
}
SlidingTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
final float density = getResources().getDisplayMetrics().density;
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
final int themeForegroundColor = outValue.data;
mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
mDefaultTabColorizer = new SimpleTabColorizer();
mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
mBottomBorderPaint = new Paint();
mBottomBorderPaint.setColor(mDefaultBottomBorderColor);
mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
mSelectedIndicatorPaint = new Paint();
}
/**
* Set the alpha value of the {#code color} to be the given {#code alpha} value.
*/
private static int setColorAlpha(int color, byte alpha) {
return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
}
/**
* Blend {#code color1} and {#code color2} using the given ratio.
*
* #param ratio of which to blend. 1.0 will return {#code color1}, 0.5 will give an even blend,
* 0.0 will return {#code color2}.
*/
private static int blendColors(int color1, int color2, float ratio) {
final float inverseRation = 1f - ratio;
float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
return Color.rgb((int) r, (int) g, (int) b);
}
void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
mCustomTabColorizer = customTabColorizer;
invalidate();
}
void setSelectedIndicatorColors(int... colors) {
// Make sure that the custom colorizer is removed
mCustomTabColorizer = null;
mDefaultTabColorizer.setIndicatorColors(colors);
invalidate();
}
void onViewPagerPageChanged(int position, float positionOffset) {
mSelectedPosition = position;
mSelectionOffset = positionOffset;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
final int height = getHeight();
final int childCount = getChildCount();
final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
? mCustomTabColorizer
: mDefaultTabColorizer;
// Thick colored underline below the current selection
if (childCount > 0) {
View selectedTitle = getChildAt(mSelectedPosition);
int left = selectedTitle.getLeft();
int right = selectedTitle.getRight();
int color = tabColorizer.getIndicatorColor(mSelectedPosition);
if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
if (color != nextColor) {
color = blendColors(nextColor, color, mSelectionOffset);
}
// Draw the selection partway between the tabs
View nextTitle = getChildAt(mSelectedPosition + 1);
left = (int) (mSelectionOffset * nextTitle.getLeft() +
(1.0f - mSelectionOffset) * left);
right = (int) (mSelectionOffset * nextTitle.getRight() +
(1.0f - mSelectionOffset) * right);
}
mSelectedIndicatorPaint.setColor(color);
canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
height, mSelectedIndicatorPaint);
}
// Thin underline along the entire bottom edge
canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
}
private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
private int[] mIndicatorColors;
#Override
public final int getIndicatorColor(int position) {
return mIndicatorColors[position % mIndicatorColors.length];
}
void setIndicatorColors(int... colors) {
mIndicatorColors = colors;
}
}
}
public class SlidingTabLayout extends HorizontalScrollView {
private static final int TITLE_OFFSET_DIPS = 24;
private static final int TAB_VIEW_PADDING_DIPS = 16;
private static final int TAB_VIEW_TEXT_SIZE_SP = 12;
private final SlidingTabStrip mTabStrip;
private int mTitleOffset;
private int mTabViewLayoutId;
private int mTabViewTextViewId;
private boolean mDistributeEvenly;
private ViewPager mViewPager;
private SparseArray<String> mContentDescriptions = new SparseArray<String>();
private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
public SlidingTabLayout(Context context) {
this(context, null);
}
public SlidingTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Disable the Scroll Bar
setHorizontalScrollBarEnabled(false);
// Make sure that the Tab Strips fills this View
setFillViewport(true);
mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
/**
* Set the custom {#link TabColorizer} to be used.
* <p/>
* If you only require simple custmisation then you can use
* {#link #setSelectedIndicatorColors(int...)} to achieve
* similar effects.
*/
public void setCustomTabColorizer(TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
/**
* Sets the colors to be used for indicating the selected tab. These colors are treated as a
* circular array. Providing one color will mean that all tabs are indicated with the same color.
*/
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
/**
* Set the {#link ViewPager.OnPageChangeListener}. When using {#link SlidingTabLayout} you are
* required to set any {#link ViewPager.OnPageChangeListener} through this method. This is so
* that the layout can update it's scroll position correctly.
*
* #see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
*/
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
/**
* Set the custom layout to be inflated for the tab views.
*
* #param layoutResId Layout id to be inflated
* #param textViewId id of the {#link TextView} in the inflated view
*/
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
/**
* Sets the associated view pager. Note that the assumption here is that the pager content
* (number of tabs and tab titles) does not change after this call has been made.
*/
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.setOnPageChangeListener(new InternalViewPagerListener());
populateTabStrip();
}
}
/**
* Create a default view to be used for tabs. This is called if a custom tab view is not set via
* {#link #setCustomTabView(int, int)}.
*/
protected TextView createDefaultTabView(Context context) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
outValue, true);
textView.setBackgroundResource(outValue.resourceId);
textView.setAllCaps(true);
int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new TabClickListener();
for (int i = 0; i < adapter.getCount(); i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
// If there is a custom tab view layout id set, try and inflate it
tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
false);
tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
}
if (tabView == null) {
tabView = createDefaultTabView(getContext());
}
if (tabTitleView == null && TextView.class.isInstance(tabView)) {
tabTitleView = (TextView) tabView;
}
if (mDistributeEvenly) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
lp.width = 0;
lp.weight = 1;
}
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
}
}
public void setContentDescription(int i, String desc) {
mContentDescriptions.put(i, desc);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mViewPager != null) {
scrollToTab(mViewPager.getCurrentItem(), 0);
}
}
private void scrollToTab(int tabIndex, int positionOffset) {
final int tabStripChildCount = mTabStrip.getChildCount();
if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
return;
}
View selectedChild = mTabStrip.getChildAt(tabIndex);
if (selectedChild != null) {
int targetScrollX = selectedChild.getLeft() + positionOffset;
if (tabIndex > 0 || positionOffset > 0) {
// If we're not at the first child and are mid-scroll, make sure we obey the offset
targetScrollX -= mTitleOffset;
}
scrollTo(targetScrollX, 0);
}
}
/**
* Allows complete control over the colors drawn in the tab layout. Set with
* {#link #setCustomTabColorizer(TabColorizer)}.
*/
public interface TabColorizer {
/**
* #return return the color of the indicator used when {#code position} is selected.
*/
int getIndicatorColor(int position);
}
private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
private int mScrollState;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
int tabStripChildCount = mTabStrip.getChildCount();
if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
return;
}
mTabStrip.onViewPagerPageChanged(position, positionOffset);
View selectedTitle = mTabStrip.getChildAt(position);
int extraOffset = (selectedTitle != null)
? (int) (positionOffset * selectedTitle.getWidth())
: 0;
scrollToTab(position, extraOffset);
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
positionOffsetPixels);
}
}
#Override
public void onPageScrollStateChanged(int state) {
mScrollState = state;
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageScrollStateChanged(state);
}
}
#Override
public void onPageSelected(int position) {
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
mTabStrip.onViewPagerPageChanged(position, 0f);
scrollToTab(position, 0);
}
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
mTabStrip.getChildAt(i).setSelected(position == i);
}
if (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageSelected(position);
}
}
}
private class TabClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
return;
}
}
}
}
}
On both classes from google they have no declared the colorForeground so I am assuming it is set into Android? Any help would be greatly appreciated on fixing this issue with the colorForeground.
It is because android is not able to find R.attr.colorForeground since you (just as I did once) imported your own R into SlidingTabStrip. It is better to import import android.R; (Android Studio warns not to, tho) or use android.R.attr.colorForeground directly.
There is a difference between:
android.R;
is used for accessing public standard android SDK resources.
and
com.yourpackage.R;
is used for accessing YOUR resources in your application.
You can use both, but if you are using your R reference, you MUST explicitly resolve either depending on where/what you need
Remove your own package say ex: com.yourpackage.R.
Place android.R.attr.colorForeground instead of R.attr.colorForeground
i'm using youtubeApi (https://developers.google.com/youtube/android/player/downloads/), I'm looking for a solution for put an onclick listener on the videos on the VideoWall..
package com.android.youbho.Activities;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayer.PlayerStyle;
import com.google.android.youtube.player.YouTubePlayerFragment;
import com.google.android.youtube.player.YouTubeThumbnailLoader;
import com.google.android.youtube.player.YouTubeThumbnailView;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.Toast;
import com.android.youbho.Utils.Constant;
import com.android.youbho.Utils.FlippingView;
import com.android.youbho.Utils.ImageWallView;
#SuppressLint("NewApi") public class VideoWallActivity extends Activity implements
FlippingView.Listener,
YouTubePlayer.OnInitializedListener,
YouTubeThumbnailView.OnInitializedListener{
private static final int RECOVERY_DIALOG_REQUEST = 1;
/** The player view cannot be smaller than 110 pixels high. */
private static final float PLAYER_VIEW_MINIMUM_HEIGHT_DP = 110;
private static final int MAX_NUMBER_OF_ROWS_WANTED = 4;
// Example playlist from which videos are displayed on the video wall
private static final String PLAYLIST_ID = "PLBA95EAD360E2B0D1";
private static final int INTER_IMAGE_PADDING_DP = 5;
// YouTube thumbnails have a 16 / 9 aspect ratio
private static final double THUMBNAIL_ASPECT_RATIO = 16 / 9d;
private static final int INITIAL_FLIP_DURATION_MILLIS = 100;
private static final int FLIP_DURATION_MILLIS = 500;
private static final int FLIP_PERIOD_MILLIS = 2000;
private ImageWallView imageWallView;
private Handler flipDelayHandler;
private FlippingView flippingView;
private YouTubeThumbnailView thumbnailView;
private YouTubeThumbnailLoader thumbnailLoader;
private YouTubePlayerFragment playerFragment;
private View playerView;
private YouTubePlayer player;
private Dialog errorDialog;
private int flippingCol;
private int flippingRow;
private int videoCol;
private int videoRow;
private boolean nextThumbnailLoaded;
private boolean activityResumed;
private State state;
private static final int id_videoPlayer=99;
private enum State {
UNINITIALIZED,
LOADING_THUMBNAILS,
VIDEO_FLIPPED_OUT,
VIDEO_LOADING,
VIDEO_CUED,
VIDEO_PLAYING,
VIDEO_ENDED,
VIDEO_BEING_FLIPPED_OUT,
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
Toast.makeText(getApplicationContext(), "lol:" + position, Toast.LENGTH_LONG).show();
return view;
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB) #SuppressLint("NewApi") #Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
state = State.UNINITIALIZED;
ViewGroup viewFrame = new FrameLayout(this);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int maxAllowedNumberOfRows = (int) Math.floor((displayMetrics.heightPixels / displayMetrics.density) / PLAYER_VIEW_MINIMUM_HEIGHT_DP);
int numberOfRows = Math.min(maxAllowedNumberOfRows, MAX_NUMBER_OF_ROWS_WANTED);
int interImagePaddingPx = (int) displayMetrics.density * INTER_IMAGE_PADDING_DP;
int imageHeight = (displayMetrics.heightPixels / numberOfRows) - interImagePaddingPx;
int imageWidth = (int) (imageHeight * THUMBNAIL_ASPECT_RATIO);
imageWallView = new ImageWallView(this, imageWidth, imageHeight, interImagePaddingPx);
viewFrame.addView(imageWallView, MATCH_PARENT, MATCH_PARENT);
thumbnailView = new YouTubeThumbnailView(this);
thumbnailView.initialize(Constant.DEVELOPER_KEY, this);
flippingView = new FlippingView(this, this, imageWidth, imageHeight);
flippingView.setFlipDuration(INITIAL_FLIP_DURATION_MILLIS);
viewFrame.addView(flippingView, imageWidth, imageHeight);
playerView = new FrameLayout(this);
playerView.setId(id_videoPlayer);
playerView.setVisibility(View.INVISIBLE);
viewFrame.addView(playerView, imageWidth, imageHeight);
playerFragment = YouTubePlayerFragment.newInstance();
playerFragment.initialize(Constant.DEVELOPER_KEY, this);
getFragmentManager().beginTransaction().add(id_videoPlayer, playerFragment).commit();
flipDelayHandler = new FlipDelayHandler();
setContentView(viewFrame);
}
#Override
public void onInitializationSuccess(YouTubeThumbnailView thumbnailView, YouTubeThumbnailLoader thumbnailLoader) {
thumbnailView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "lol! ", Toast.LENGTH_LONG).show();
}
});
this.thumbnailLoader = thumbnailLoader;
thumbnailLoader.setOnThumbnailLoadedListener(new ThumbnailListener());
maybeStartDemo();
}
#Override
public void onInitializationFailure(YouTubeThumbnailView thumbnailView, YouTubeInitializationResult errorReason) {
if (errorReason.isUserRecoverableError()) {
if (errorDialog == null || !errorDialog.isShowing()) {
errorDialog = errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST);
errorDialog.show();
}
} else {
String errorMessage = String.format( errorReason.toString());
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasResumed) {
VideoWallActivity.this.player = player;
player.setPlayerStyle(PlayerStyle.CHROMELESS);
player.setPlayerStateChangeListener(new VideoListener());
maybeStartDemo();
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult errorReason) {
if (errorReason.isUserRecoverableError()) {
if (errorDialog == null || !errorDialog.isShowing()) {
errorDialog = errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST);
errorDialog.show();
}
} else {
String errorMessage = String.format( errorReason.toString());
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
}
private void maybeStartDemo() {
if (activityResumed && player != null && thumbnailLoader != null && state.equals(State.UNINITIALIZED)) {
thumbnailLoader.setPlaylist(PLAYLIST_ID); // loading the first thumbnail will kick off demo
state = State.LOADING_THUMBNAILS;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECOVERY_DIALOG_REQUEST) {
// Retry initialization if user performed a recovery action
if (errorDialog != null && errorDialog.isShowing()) {
errorDialog.dismiss();
}
errorDialog = null;
playerFragment.initialize(Constant.DEVELOPER_KEY, this);
thumbnailView.initialize(Constant.DEVELOPER_KEY, this);
}
}
#Override
protected void onResume() {
super.onResume();
activityResumed = true;
if (thumbnailLoader != null && player != null) {
if (state.equals(State.UNINITIALIZED)) {
maybeStartDemo();
} else if (state.equals(State.LOADING_THUMBNAILS)) {
loadNextThumbnail();
} else {
if (state.equals(State.VIDEO_PLAYING)) {
player.play();
}
flipDelayHandler.sendEmptyMessageDelayed(0, FLIP_DURATION_MILLIS);
}
}
}
#Override
protected void onPause() {
flipDelayHandler.removeCallbacksAndMessages(null);
activityResumed = false;
super.onPause();
}
#Override
protected void onDestroy() {
if (thumbnailLoader != null) {
thumbnailLoader.release();
}
super.onDestroy();
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB) private void flipNext() {
if (!nextThumbnailLoaded || state.equals(State.VIDEO_LOADING)) {
return;
}
if (state.equals(State.VIDEO_ENDED)) {
flippingCol = videoCol;
flippingRow = videoRow;
state = State.VIDEO_BEING_FLIPPED_OUT;
} else {
Pair<Integer, Integer> nextTarget = imageWallView.getNextLoadTarget();
flippingCol = nextTarget.first;
flippingRow = nextTarget.second;
}
flippingView.setX(imageWallView.getXPosition(flippingCol, flippingRow));
flippingView.setY(imageWallView.getYPosition(flippingCol, flippingRow));
flippingView.setFlipInDrawable(thumbnailView.getDrawable());
flippingView.setFlipOutDrawable(imageWallView.getImageDrawable(flippingCol, flippingRow));
imageWallView.setImageDrawable(flippingCol, flippingRow, thumbnailView.getDrawable());
imageWallView.hideImage(flippingCol, flippingRow);
flippingView.setVisibility(View.VISIBLE);
flippingView.flip();
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB) #Override
public void onFlipped(FlippingView view) {
imageWallView.showImage(flippingCol, flippingRow);
flippingView.setVisibility(View.INVISIBLE);
if (activityResumed) {
loadNextThumbnail();
if (state.equals(State.VIDEO_BEING_FLIPPED_OUT)) {
state = State.VIDEO_FLIPPED_OUT;
} else if (state.equals(State.VIDEO_CUED)) {
videoCol = flippingCol;
videoRow = flippingRow;
playerView.setX(imageWallView.getXPosition(flippingCol, flippingRow));
playerView.setY(imageWallView.getYPosition(flippingCol, flippingRow));
imageWallView.hideImage(flippingCol, flippingRow);
playerView.setVisibility(View.VISIBLE);
player.play();
state = State.VIDEO_PLAYING;
} else if (state.equals(State.LOADING_THUMBNAILS) && imageWallView.allImagesLoaded()) {
state = State.VIDEO_FLIPPED_OUT; // trigger flip in of an initial video
flippingView.setFlipDuration(FLIP_DURATION_MILLIS);
flipDelayHandler.sendEmptyMessage(0);
}
}
}
private void loadNextThumbnail() {
nextThumbnailLoaded = false;
if (thumbnailLoader.hasNext()) {
thumbnailLoader.next();
} else {
thumbnailLoader.first();
}
}
/**
* A handler that periodically flips an element on the video wall.
*/
#SuppressLint("HandlerLeak")
private final class FlipDelayHandler extends Handler {
#Override
public void handleMessage(Message msg) {
flipNext();
sendEmptyMessageDelayed(0, FLIP_PERIOD_MILLIS);
}
}
/**
* An internal listener which listens to thumbnail loading events from the
* {#link YouTubeThumbnailView}.
*/
private final class ThumbnailListener implements YouTubeThumbnailLoader.OnThumbnailLoadedListener {
#Override
public void onThumbnailLoaded(YouTubeThumbnailView thumbnail, String videoId) {
nextThumbnailLoaded = true;
if (activityResumed) {
if (state.equals(State.LOADING_THUMBNAILS)) {
flipNext();
} else if (state.equals(State.VIDEO_FLIPPED_OUT)) {
// load player with the video of the next thumbnail being flipped in
state = State.VIDEO_LOADING;
player.cueVideo(videoId);
}
}
}
#Override
public void onThumbnailError(YouTubeThumbnailView thumbnail, YouTubeThumbnailLoader.ErrorReason reason) {
loadNextThumbnail();
}
}
private final class VideoListener implements YouTubePlayer.PlayerStateChangeListener {
#Override
public void onLoaded(String videoId) {
state = State.VIDEO_CUED;
}
#Override
public void onVideoEnded() {
state = State.VIDEO_ENDED;
imageWallView.showImage(videoCol, videoRow);
playerView.setVisibility(View.INVISIBLE);
}
#Override
public void onError(YouTubePlayer.ErrorReason errorReason) {
if (errorReason == YouTubePlayer.ErrorReason.UNEXPECTED_SERVICE_DISCONNECTION) {
// player has encountered an unrecoverable error - stop the demo
flipDelayHandler.removeCallbacksAndMessages(null);
state = State.UNINITIALIZED;
thumbnailLoader.release();
thumbnailLoader = null;
player = null;
} else {
state = State.VIDEO_ENDED;
}
}
// ignored callbacks
#Override
public void onVideoStarted() { }
#Override
public void onAdStarted() { }
#Override
public void onLoading() { }
}
}
In this way, there are a list of videos in the playlist, each video will start automatically when the first is finished. I need to click each video in the wall for start it
You can add an onClickListener to the ImageViews in the ImageWallView.java class, something like this:
for (int col = 0; col < numberOfColumns; col++) {
for (int row = 0; row < numberOfRows; row++) {
int elementIdx = getElementIdx(col, row);
if (images[elementIdx] == null) {
ImageView thumbnail = new ImageView(context);
thumbnail.setLayoutParams(new LayoutParams(imageWidth, imageHeight));
images[elementIdx] = thumbnail;
unInitializedImages.add(elementIdx);
thumbnail.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ImageWallView.this.context.startActivity(YouTubeIntents.createPlayVideoIntentWithOptions(
ImageWallView.this.context, (String)v.getTag(), true, false));
}
});
}
addView(images[elementIdx]);
}
}
Then you will need to add the video id as the tag in YouTubeThumbnailView in VideoWallActivity.java
Hope that helps
You can use ImageView OnClickListener as suggested in previous answer: (onSizeChanged in ImageWallView.java)
for (int col = 0; col < numberOfColumns; col++) {
for (int row = 0; row < numberOfRows; row++) {
int elementIdx = getElementIdx(col, row);
if (images[elementIdx] == null) {
ImageView thumbnail = new ImageView(context);
thumbnail.setLayoutParams(new LayoutParams(imageWidth, imageHeight));
images[elementIdx] = thumbnail;
unInitializedImages.add(elementIdx);
thumbnail.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ImageWallView.this.context.startActivity(YouTubeIntents.createPlayVideoIntentWithOptions(
ImageWallView.this.context, (String)v.getTag(), true, false));
}
});
}
addView(images[elementIdx]);
}
}
Then you need to store video id to the calling view of ImageWallView . (set and get tag is also used to store objects between views).
To get the child view of ImageWallView, use imageWallView.getChildAt(index). index is the position of ImageView which is clicked on ImageWallView. to get this index, use getElementIdx(col,row). You need to make this method public in ImageWallView.java.
EDITED
To use the Video ID of current thumbnail, Store the VideoID in onFlipped event. This is because onThumbnailLoaded the VideoID of next thumbnail available which immediately get Flipped and available on IamgeWallView. As VideoID is not available in onFlipped event, use it from onThumbnailLoaded event
Here it is:
Declare below string in class
private String strThumbnailVideoId;
set VideoID in onThumbnailLoaded event (in VideoWallActivity.java) into strThumbnailVideoId. This video ID will be of next thumbnail which will be flipped.
#Override
public void onThumbnailLoaded(YouTubeThumbnailView thumbnail, String videoId) {
nextThumbnailLoaded = true;
strThumbnailVideoId = videoId;
if (activityResumed) {
if (state.equals(State.LOADING_THUMBNAILS)) {
flipNext();
} else if (state.equals(State.VIDEO_FLIPPED_OUT)) {
// load player with the video of the next thumbnail being flipped in
state = State.VIDEO_LOADING;
player.cueVideo(videoId);
}
}
}
Now set the strThumbnailVideoId in onFlipped as a ImageWallView tag.
#Override
public void onFlipped(FlippingView view) {
imageWallView.showImage(flippingCol, flippingRow);
flippingView.setVisibility(View.INVISIBLE);
imageWallView.getChildAt(imageWallView.getElementIdx(flippingCol, flippingRow)).setTag(strThumbnailVideoId);
......
......