I've been struggling with tab implementation in my application and seen a lot of resources on the matter but nothing appears to be working for me. I just want 4 simple tabs with icons above my toolbar, that's all. Can someone help me out on achieving this?
Here's my code if needed:
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class ProjectCreateScreen extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.secondary_layout1);
Toolbar toolbar = (Toolbar) findViewById(R.id.AwesomeBar);
setSupportActionBar(toolbar);
}
public void displayProjectOptions (View view) {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_primary, menu);
return true;
}
final ArrayList<String> listItems=new ArrayList<String>();
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.addButton) {
final TextView noProject = (TextView) findViewById(R.id.NOPROJECT);
final ListAdapter addAdapter = new ArrayAdapter<String>(this,
R.layout.list_item, R.id.listFrame, listItems);
final ListView lv = (ListView) findViewById(R.id.lv);
lv.setAdapter(addAdapter);
noProject.setVisibility(View.GONE);
lv.setVisibility(View.VISIBLE);
listItems.add("New Project");
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent switchToEdit = new Intent(ProjectCreateScreen.this,
teamCreateScreen.class);
startActivity(switchToEdit);
}
});
}
return super.onOptionsItemSelected(item);
}
}
And xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rl">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/actionBarSize"
android:id="#+id/AwesomeBar"
android:background="#color/custom_white">
</android.support.v7.widget.Toolbar>
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="#string/noProjectsNotice"
android:id="#+id/NOPROJECT"
android:gravity="center"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textSize="16sp"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/AwesomeBar"
android:id="#+id/lv"
android:visibility="invisible">
</ListView>
If you are using toolbar you need to use SlidingTabLayout for tabs in toolbar as follows
TabFragment.java
public class TabFragment extends Fragment {
private SlidingTabLayout mSlidingTabLayout;
private MyActivityAdapter mAdapter;
private ViewPager mViewPager;
private Menu mMenu;
private ScreenNames mScreenName = ScreenNames.UNRAVELING_ME;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_swipe, container, false);
mSlidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setCustomTabView(R.layout.tab_indicator, android.R.id.text1);
mSlidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.unravel_secondary_red));
mSlidingTabLayout.setDistributeEvenly(true);
mSlidingTabLayout.setBackgroundColor(Color.parseColor("#F7F7F7"));
mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener (){
#Override
public void onPageSelected(int position)
{
if(position == 0){
}
else {
}
}
#Override
public void onPageScrollStateChanged(int state)
{
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
});
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mAdapter = new MyActivityAdapter(this, getChildFragmentManager());
mViewPager.setAdapter(mAdapter);
mSlidingTabLayout.setViewPager(mViewPager);
return view;
}
fragment_swipe.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.unravel.widget.SlidingTabLayout
android:id="#+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>
MyActivityAdapter.java
public class MyActivityAdapter extends FragmentPagerAdapter {
private MyActivityFragment mFragment;
public MyActivityAdapter(MyActivityFragment fragment, FragmentManager fm) {
super(fm);
mFragment = fragment;
}
#Override
public Fragment getItem(int i) {
if (i == 0) {
return new fragment1();
}
else {
return new fragment2();
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return "first tab";
} else {
return "second tab";
}
}
}
Fragment1.java
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_fragment1, container, false);
}
}
Fragment2.java
public class Fragment2 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_fragment1, container, false);
}
}
SlidingTabLayout.java
public class SlidingTabLayout extends HorizontalScrollView {
/**
* 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 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 = 18;
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;
private final SlidingTabStrip mTabStrip;
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.
*
* 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);
}
}
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;
}
}
}
}
}
SlidingTabStrip.java
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 = 2;
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 int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout.TabColorizer mCustomTabColorizer;
private final SimpleTabColorizer mDefaultTabColorizer;
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(android.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();
}
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);
}
/**
* 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);
}
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;
}
}
}
Related
I’m trying to pass the position of the card to SlideView Activity where onMenuItemClick was used to bring up the correct information about that specific card. Currently, I’m using getAdapterPosition in onMenuItemClick within my Adapter, but thats resulting in the last element drawn to screen being saved to my adapterPosition. I understand why it’s giving the last position, but unsure how to set the correct position. Should I try to save and pass the position via showPopupMenu or something else entirely? Below are my Adapter & MainActivity.
Adapter:
public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
private Context mContext;
private List<Properties> dogList;
private MyViewHolder holder;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title, count;
public ImageView thumbnail, overflow;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
count = (TextView) view.findViewById(R.id.count);
thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
overflow = (ImageView) view.findViewById(R.id.overflow);
}
}
public Adapter(Context mContext, List<Properties> dogList) {
this.mContext = mContext;
this.dogList = dogList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
this.holder=holder;
Properties dog = dogList.get(position);
holder.title.setText(dog.getName());
// loading dog cover using Glide library
Glide.with(mContext).load(dog.getThumbnail()).into(holder.thumbnail);
holder.overflow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showPopupMenu(holder.overflow);
}
});
}
/**
* Showing popup menu when tapping on icon
*/
private void showPopupMenu(View view) {
// inflate menu
PopupMenu popup = new PopupMenu(mContext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu, popup.getMenu());
popup.setOnMenuItemClickListener(new MyMenuItemClickListener());
popup.show();
}
/**
* Click listener for popup menu items
*/
class MyMenuItemClickListener implements PopupMenu.OnMenuItemClickListener {
public MyMenuItemClickListener() {
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_add_favourite:
Toast.makeText(mContext, "Add to favourite", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_more_info:
Intent slideStart = new Intent(mContext, SlideViewActivity.class);
super.getClass();
int adapterPosition = holder.getAdapterPosition();
slideStart.putExtra("position", adapterPosition);
slideStart.putExtra("list", (Serializable) dogList);
mContext.startActivity(slideStart);
return true;
default:
}
return false;
}
}
#Override
public int getItemCount() {
return dogList.size();
}
}
MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private RecyclerView recyclerView;
private Adapter adapter;
private List<Properties> dogList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initCollapsingToolbar();
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
dogList = new ArrayList<>();
adapter = new Adapter(this, dogList);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
prepareCards();
try {
Glide.with(this).load(R.drawable.austrailian_shepherd).into((ImageView) findViewById(R.id.backdrop));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Initializing collapsing toolbar
* Will show and hide the toolbar title on scroll
*/
private void initCollapsingToolbar() {
final CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle(" ");
AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
appBarLayout.setExpanded(true);
// hiding & showing the title when toolbar expanded & collapsed
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0) {
collapsingToolbar.setTitle(getString(R.string.app_name));
isShow = true;
} else if (isShow) {
collapsingToolbar.setTitle(" ");
isShow = false;
}
}
});
}
private void prepareCards() {
int librarySize = getResources().getStringArray(R.array.titles).length;
for(int i=0;i<librarySize;i++) {
String dognames = getResources().getStringArray(R.array.titles)[i];
String doginfo = getResources().getStringArray(R.array.info)[i];
int imageId = getResources().getIdentifier(dognames.toLowerCase(Locale.getDefault()), "drawable", this.getPackageName());
Properties a = new Properties(dognames, doginfo, imageId);
dogList.add(a);
}
adapter.notifyDataSetChanged();
}
#Override
public void onClick(View v) {
}
/**
* RecyclerView item decoration - give equal margin around grid item
*/
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
/**
* Converting dp to pixel
*/
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
}
Try these modifications :
holder.overflow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showPopupMenu(holder.overflow, position);
}
});
private void showPopupMenu(View view, int pos) {
// inflate menu
PopupMenu popup = new PopupMenu(mContext, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu, popup.getMenu());
popup.setOnMenuItemClickListener(new MyMenuItemClickListener(pos));
popup.show();
}
class MyMenuItemClickListener implements PopupMenu.OnMenuItemClickListener {
int pos;
public MyMenuItemClickListener(int pos) {
this.pos = pos;
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_add_favourite:
Toast.makeText(mContext, "Add to favourite", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_more_info:
Intent slideStart = new Intent(mContext, SlideViewActivity.class);
super.getClass();
slideStart.putExtra("position", pos);
slideStart.putExtra("list", (Serializable) dogList);
mContext.startActivity(slideStart);
return true;
default:
}
return false;
}
}
I Want a tabbed activity for that I have used sliding tabbed layout and tab strip. But don't know why I am getting two strips like below: enter image description here
SlidingTabLayout
public class SlidingTabLayout extends HorizontalScrollView {
public interface TabColorizer {
int getIndicatorColor(int position);
}
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 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;
private final SlidingTabStrip mTabStrip;
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);
setHorizontalScrollBarEnabled(false);
setFillViewport(true);
mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
public void setCustomTabColorizer(TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.setOnPageChangeListener(new InternalViewPagerListener());
populateTabStrip();
}
}
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 OnClickListener tabClickListener = new TabClickListener();
for (int i = 0; i < adapter.getCount(); i++) {
View tabView = null;
TextView tabTitleView = null;
if (mTabViewLayoutId != 0) {
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);
}
tabTitleView.setTextColor(getResources().getColorStateList(R.color.selector));
tabTitleView.setTextSize(16);
}
}
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) {
targetScrollX -= mTitleOffset;
}
scrollTo(targetScrollX, 0);
}
}
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 OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
return;
}
}
}
}
}
SlidingTabStrip
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 int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout.TabColorizer mCustomTabColorizer;
private final SimpleTabColorizer mDefaultTabColorizer;
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();
}
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);
}
/**
* 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);
}
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;
}
}
}
GoFoodCategoryFragment
public class GoFoodCategoryFragment extends Fragment{
private ViewPager pager;
private HomeViewPagerAdapter adapter;
private SlidingTabLayout tabs;
private CharSequence Titles[]={"CATEGORY","NEAR ME"};
private int Numboftabs =2;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_go_food, container, false);
setupUI(view);
return view;
}
void setupUI(View view)
{
adapter = new HomeViewPagerAdapter(this.getFragmentManager(),Titles,Numboftabs);
pager = (ViewPager) view.findViewById(R.id.pager);
pager.setAdapter(adapter);
tabs = (SlidingTabLayout) view.findViewById(R.id.tabs);
tabs.setDistributeEvenly(true);
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tab_scroll_color);
}
});
tabs.setViewPager(pager);
}
}
GoFoodCategoryLayout
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context="com.adgatemedia.offerwallsdk.fragments.MainFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.siddhi.go_jek.SlidingTabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
android:layout_marginTop="?attr/actionBarSize"
android:background="#color/colorPrimary"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_below="#+id/tabs" />
</RelativeLayout>
</FrameLayout>
HomeViewPagerAdapter
public class HomeViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[];
int NumbOfTabs;
public HomeViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
#Override
public Fragment getItem(int position) {
if(position == 0)
{
GoFoodCategoryFragment tab1 = new GoFoodCategoryFragment();
return tab1;
}
else
{
GoFoodNearMeFragment tab2 = new GoFoodNearMeFragment();
return tab2;
}
}
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
#Override
public int getCount() {
return NumbOfTabs;
}
}
Can anyone help me out with this please..
This is happening because you are using a ViewPager and SlidingTabLayout. You are basically implementing two different tab methods. You only need the ViewPager with an Adapter like so:
private class MainPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragmentList = new ArrayList<>();
private final List<String> fragmentTitles = new ArrayList<>();
public MainPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
return fragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
fragmentList.add(fragment);
fragmentTitles.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitles.get(position);
}
}
Code for setting up the ViewPager with said adapter:
MainPagerAdapter mainPagerAdapter = new MainPagerAdapter(getSupportFragmentManager());
Resources resources = this.getResources();
mainPagerAdapter.addFragment(fragmentOne, "fragmentOneTitle");
mainPagerAdapter.addFragment(fragmentTwo, "fragmentTwoTitle");
mViewPager.setAdapter(mainPagerAdapter);
I have a grid View In which I am adding Button dynamically.
I am setting OnTouch listener to grid view.
I want when my finger move on the particular cell then that cell element should get popup
similar way our android keyboard do.
public class MainActivity extends Activity {
private ArrayList<Integer> data;
private GridView gv;
private TextView biggerView = null;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createData();
gv = (GridView) findViewById(R.id.grid);
gv.setNumColumns(10);
gv.setAdapter(new FilterButtonAdapter(data, this));
gv.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
try {
int position = gv.pointToPosition((int) event.getX(),
(int) event.getY());
View v = (View) gv.getChildAt(position);
if (v != null) {
gv.requestFocus();
gv.setSelection(gv.pointToPosition( (int)
event.getX(), (int) event.getY()));
}
return true;
} catch (Exception e) {
return true;
}
}
if (event.getAction() == MotionEvent.ACTION_UP) {
int position = gv.pointToPosition((int) event.getX(),
(int) event.getY());
View v = (View) gv.getChildAt(position);
if (v != null) {
gv.clearFocus();
TextView tv = (TextView) v.findViewById(R.id.texttoadd);
Toast.makeText(MainActivity.this, tv.getText(),
Toast.LENGTH_SHORT).show();
}
return true;
}
return false;
}
});
}
private void createData() {
data = new ArrayList<Integer>();
for (int i = 0; i < 200; i++) {
data.add(i);
}
}
enter code here
i have write this code which is giving me the selected item but when item are more then grid is scrolled and after that the am not getting the item which i am selecting
i have figured out that the x and y position is getting change when grid is scrolled
i may be wrong
please help
I think that suggested in the question way of touch position detection might be not effective, because there's more high-level way to obtain scrolling position.
The main ideas of the implementation are the following:
Use onScrollChanged() to track scroll position at every moment;
Display selection as separate view above GridView;
Track if selected item is visible (using this question);
So, to obtain proper scroll callback, slightly customized GridView is needed:
public class ScrollAwareGridView extends GridView {
/** Callback interface to report immediate scroll changes */
public interface ImmediateScrollListener {
void onImmediateScrollChanged();
}
/** External listener for */
private ImmediateScrollListener mScrollListener = null;
public ScrollAwareGridView(final Context context) {
super(context);
}
public ScrollAwareGridView(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public ScrollAwareGridView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (null != mScrollListener) {
mScrollListener.onImmediateScrollChanged();
}
}
/**
* #param listener {#link ImmediateScrollListener}
*/
public void setImmediateScrollListener(final ImmediateScrollListener listener) {
mScrollListener = listener;
}
}
It will be placed in the xml the following way (main.xml):
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.TestApp.ScrollAwareGridView
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3" />
<!-- Selection view -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/selectedImage"
android:visibility="gone" />
</RelativeLayout>
In above xml there's also selection view presented.
Activity will handle selection of items (however, it might be better to keep selection and scroll tracking logic in separate object (grid adapter or specific grid fragment) in order not to keep grid-specific logic in Activity code):
public class MyActivity extends Activity implements ScrollAwareGridView.ImmediateScrollListener, AdapterView.OnItemClickListener {
private static final String TAG = "MyActivity";
/** To start / pause music */
private ImageView mSelectedImage = null;
/** position of selected item in the adapter */
private int mSelectedPosition;
/** Main grid view */
private ScrollAwareGridView mGrid;
/** Adapter for grid view */
private ImageAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show the layout with the test view
setContentView(R.layout.main);
mSelectedImage = (ImageView) findViewById(R.id.selectedImage);
mGrid = (ScrollAwareGridView) findViewById(R.id.grid);
if (null != mGrid) {
mAdapter = new ImageAdapter(this);
mGrid.setAdapter(mAdapter);
mGrid.setImmediateScrollListener(this);
mGrid.setOnItemClickListener(this);
}
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
mSelectedImage.setImageBitmap(null);
mSelectedImage.setVisibility(View.GONE);
mSelectedPosition = -1;
}
#Override
public void onImmediateScrollChanged() {
if (mSelectedPosition >= 0) {
int firstPosition = mGrid.getFirstVisiblePosition(); // This is the same as child #0
int wantedChild = mSelectedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= mGrid.getChildCount()) {
Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
mSelectedImage.setVisibility(View.INVISIBLE);
return;
} else {
mSelectedImage.setVisibility(View.VISIBLE);
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
final View selectedView = mGrid.getChildAt(wantedChild);
if (null != selectedView && mSelectedImage.getVisibility() == View.VISIBLE) {
// Put selected view on new position
final ViewGroup.MarginLayoutParams zoomedImageLayoutParams = (ViewGroup.MarginLayoutParams) mSelectedImage.getLayoutParams();
// 200 is difference between zoomed and not zoomed images dimensions
// TODO: Avoid hardcoded values and use resources
final Integer thumbnailX = mGrid.getLeft() + selectedView.getLeft() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION) / 2;
final Integer thumbnailY = mGrid.getTop() + selectedView.getTop() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION) / 2;
zoomedImageLayoutParams.setMargins(thumbnailX,
thumbnailY,
0,
0);
mSelectedImage.setLayoutParams(zoomedImageLayoutParams);
}
}
}
#Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
mSelectedPosition = position;
final Bitmap bm = mAdapter.getImage(position);
// Obtain image from adapter, with check if image presented
if (bm != null) {
final ViewGroup.MarginLayoutParams zoomedImageLayoutParams = (ViewGroup.MarginLayoutParams) mSelectedImage.getLayoutParams();
// 200 is difference between zoomed and not zoomed images dimensions
// TODO: Avoid hardcoded values and use resources
final Integer thumbnailX = mGrid.getLeft() + view.getLeft() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION) / 2;
final Integer thumbnailY = mGrid.getTop() + view.getTop() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION) / 2;
zoomedImageLayoutParams.setMargins(thumbnailX,
thumbnailY,
0,
0);
zoomedImageLayoutParams.height = ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION;
zoomedImageLayoutParams.width = ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION;
mSelectedImage.setImageBitmap(bm);
mSelectedImage.setScaleType(ImageView.ScaleType.CENTER);
mSelectedImage.setLayoutParams(zoomedImageLayoutParams);
mSelectedImage.setVisibility(View.VISIBLE);
}
}
}
Below is GridViews adapter. However there's nothing specific in it which related to scrolling tracking (most of code I've reused from this answer):
public class ImageAdapter extends BaseAdapter {
private static final String TAG = "ImageAdapter";
/** For creation of child ImageViews */
private Context mContext;
public static final Integer[] IMAGES_RESOURCES = {
R.drawable.image001, R.drawable.image002, R.drawable.image003, R.drawable.image004,
R.drawable.image005, R.drawable.image006, R.drawable.image007, R.drawable.image008,
R.drawable.image009, R.drawable.image010, R.drawable.image011, R.drawable.image012,
R.drawable.image013, R.drawable.image014, R.drawable.image015, R.drawable.image016,
R.drawable.image017, R.drawable.image018, R.drawable.image019, R.drawable.image020,
R.drawable.image021, R.drawable.image022, R.drawable.image023, R.drawable.image024,
R.drawable.image025, R.drawable.image026, R.drawable.image027, R.drawable.image028,
R.drawable.image029, R.drawable.image030, R.drawable.image031, R.drawable.image032,
R.drawable.image033, R.drawable.image034, R.drawable.image035, R.drawable.image036,
R.drawable.image037, R.drawable.image038, R.drawable.image039, R.drawable.image040,
R.drawable.image041, R.drawable.image042, R.drawable.image043, R.drawable.image044,
R.drawable.image045, R.drawable.image046, R.drawable.image047, R.drawable.image048,
R.drawable.image049, R.drawable.image050
};
// TODO: use resources for that sizes, otherwise You'll GET PROBLEMS on other displays!
public final static int GRID_ITEM_DIMENSION = 300;
public final static int HIGHLIGHTED_GRID_ITEM_DIMENSION = 500;
private Bitmap mHolder = null;
private static final int CACHE_SIZE = 50 * 1024 * 1024; // 8 MiB cache
/** Cache to store all decoded images */
private LruCache<Integer, Bitmap> mBitmapsCache = new LruCache<Integer, Bitmap>(CACHE_SIZE) {
#Override
protected int sizeOf(final Integer key, final Bitmap value) {
return value.getByteCount();
}
#Override
protected void entryRemoved(final boolean evicted, final Integer key, final Bitmap oldValue, final Bitmap newValue) {
if (!oldValue.equals(mHolder)) {
oldValue.recycle();
}
}
};
// Constructor
public ImageAdapter(Context c){
mContext = c;
mHolder = BitmapFactory.decodeResource(c.getResources(), R.drawable.ic_launcher, null);
}
#Override
public int getCount() {
return IMAGES_RESOURCES.length;
}
#Override
public Object getItem(int position) {
return IMAGES_RESOURCES[position];
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(mContext);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(GRID_ITEM_DIMENSION, GRID_ITEM_DIMENSION));
} else {
imageView = (ImageView) convertView;
}
final Bitmap itemBitmap = mBitmapsCache.get(IMAGES_RESOURCES[position]);
if (itemBitmap == null || itemBitmap.isRecycled()) {
Log.e(TAG, position + " is missed, launch decode for " + IMAGES_RESOURCES[position]);
imageView.setImageBitmap(mHolder);
mBitmapsCache.put(IMAGES_RESOURCES[position], mHolder);
new BitmapWorkerTask(mBitmapsCache, mContext.getResources(), this).execute(IMAGES_RESOURCES[position]);
} else {
Log.e(TAG, position + " is here for " + IMAGES_RESOURCES[position]);
imageView.setImageBitmap(itemBitmap);
}
return imageView;
}
/**
* Obtains image at position (if there's only holder, then null to be returned)
*
* #param position int position in the adapter
*
* #return {#link Bitmap} image at position or null if image is not loaded yet
*/
public Bitmap getImage(final int position) {
final Bitmap bm = mBitmapsCache.get(IMAGES_RESOURCES[position]);
return ((mHolder.equals(bm) || bm == null) ? null : bm.copy(Bitmap.Config.ARGB_8888, false));
}
/** AsyncTask for decoding images from resources */
static class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private int data = 0;
private final LruCache<Integer, Bitmap> mCache;
private final Resources mRes;
private final BaseAdapter mAdapter;
public BitmapWorkerTask(LruCache<Integer, Bitmap> cache, Resources res, BaseAdapter adapter) {
// nothing to do here
mCache = cache;
mRes = res;
mAdapter = adapter;
}
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
// Use sizes for selected bitmaps for good up-scaling
return decodeSampledBitmapFromResource(mRes, data, GRID_ITEM_DIMENSION, GRID_ITEM_DIMENSION);
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
mCache.put(data, bitmap);
mAdapter.notifyDataSetChanged();
}
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.outHeight = GRID_ITEM_DIMENSION;
options.outWidth = GRID_ITEM_DIMENSION;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}
im trying to figure out how i can make this work. I have perfectly working wallpaper selector, Which loads the wallpaper as a [1]:https://www.dropbox.com/s/phu0a6atue7vlsb/Screenshot_2013-01-03-23-35-06.png
However im trying to change the code to look something like this!
The main interface like so.
https://www.dropbox.com/s/0v0wd9sx41nh2oh/Screenshot_2013-01-03-23-38-34.png
And when the "Wallpaper" is selected it bring up a ImageView of the large wallpaper
https://www.dropbox.com/s/dna7xxa1hzywwme/Screenshot_2013-01-03-23-38-55.png
Here is what i have for soure code.
Im suck on getting it changed from a Gallery to a GridView!
WallpaperChooser.java
public class WallpaperChooser extends Activity {
#SuppressWarnings("unused")
private static final String TAG = "Launcher.WallpaperChooser";
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.wallpaper_chooser_base);
Fragment fragmentView =
getFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment);
// TODO: The following code is currently not exercised. Leaving it here in case it
// needs to be revived again.
if (fragmentView == null) {
/* When the screen is XLarge, the fragment is not included in the layout, so show it
* as a dialog
*/
DialogFragment fragment = WallpaperChooserDialogFragment.newInstance();
fragment.show(getFragmentManager(), "dialog");
}
}
}
WallpaperChooserFragment.java
public class WallpaperChooserDialogFragment extends DialogFragment implements
AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
private static final String TAG = "Launcher.WallpaperChooserDialogFragment";
private static final String EMBEDDED_KEY = "com.jaisonbrooks.theme.sony.xperia."
+ "WallpaperChooserDialogFragment.EMBEDDED_KEY";
private boolean mEmbedded;
private Bitmap mBitmap = null;
private ArrayList<Integer> mThumbs;
private ArrayList<Integer> mImages;
private WallpaperLoader mLoader;
private WallpaperDrawable mWallpaperDrawable = new WallpaperDrawable();
public static WallpaperChooserDialogFragment newInstance() {
WallpaperChooserDialogFragment fragment = new WallpaperChooserDialogFragment();
fragment.setCancelable(true);
return fragment;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) {
mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY);
} else {
mEmbedded = isInLayout();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(EMBEDDED_KEY, mEmbedded);
}
private void cancelLoader() {
if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
mLoader.cancel(true);
mLoader = null;
}
}
#Override
public void onDetach() {
super.onDetach();
cancelLoader();
}
#Override
public void onDestroy() {
super.onDestroy();
cancelLoader();
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
/* On orientation changes, the dialog is effectively "dismissed" so this is called
* when the activity is no longer associated with this dying dialog fragment. We
* should just safely ignore this case by checking if getActivity() returns null
*/
Activity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
/* This will only be called when in XLarge mode, since this Fragment is invoked like
* a dialog in that mode
*/
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
findWallpapers();
return null;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
findWallpapers();
/* If this fragment is embedded in the layout of this activity, then we should
* generate a view to display. Otherwise, a dialog will be created in
* onCreateDialog()
*/
if (mEmbedded) {
View view = inflater.inflate(R.layout.wallpaper_chooser, container, false);
view.setBackground(mWallpaperDrawable);
final Gallery gallery = (Gallery) view.findViewById(R.id.gallery);
gallery.setCallbackDuringFling(false);
gallery.setOnItemSelectedListener(this);
gallery.setAdapter(new ImageAdapter(getActivity()));
View setButton = view.findViewById(R.id.set);
setButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
selectWallpaper(gallery.getSelectedItemPosition());
}
});
return view;
}
return null;
}
private void selectWallpaper(int position) {
try {
WallpaperManager wpm = (WallpaperManager) getActivity().getSystemService(
Context.WALLPAPER_SERVICE);
wpm.setResource(mImages.get(position));
Activity activity = getActivity();
activity.setResult(Activity.RESULT_OK);
activity.finish();
} catch (IOException e) {
Log.e(TAG, "Failed to set wallpaper: " + e);
}
}
// Click handler for the Dialog's GridView
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectWallpaper(position);
}
// Selection handler for the embedded Gallery view
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) {
mLoader.cancel();
}
mLoader = (WallpaperLoader) new WallpaperLoader().execute(position);
}
public void onNothingSelected(AdapterView<?> parent) {
}
private void findWallpapers() {
mThumbs = new ArrayList<Integer>(24);
mImages = new ArrayList<Integer>(24);
final Resources resources = getResources();
// Context.getPackageName() may return the "original" package name,
// com.android.launcher2; Resources needs the real package name,
// com.android.launcher. So we ask Resources for what it thinks the
// package name should be.
final String packageName = resources.getResourcePackageName(R.array.wallpapers);
addWallpapers(resources, packageName, R.array.wallpapers);
// addWallpapers(resources, packageName, R.array.extra_wallpapers);
}
private void addWallpapers(Resources resources, String packageName, int list) {
final String[] extras = resources.getStringArray(list);
for (String extra : extras) {
int res = resources.getIdentifier(extra, "drawable", packageName);
if (res != 0) {
final int thumbRes = resources.getIdentifier(extra + "_thumb",
"drawable", packageName);
if (thumbRes != 0) {
mThumbs.add(thumbRes);
mImages.add(res);
// Log.d(TAG, "add: [" + packageName + "]: " + extra + " (" + res + ")");
}
}
}
}
private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
private LayoutInflater mLayoutInflater;
ImageAdapter(Activity activity) {
mLayoutInflater = activity.getLayoutInflater();
}
public int getCount() {
return mThumbs.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false);
} else {
view = convertView;
}
ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
int thumbRes = mThumbs.get(position);
image.setImageResource(thumbRes);
Drawable thumbDrawable = image.getDrawable();
if (thumbDrawable != null) {
thumbDrawable.setDither(true);
} else {
Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #"
+ position);
}
return view;
}
}
class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> {
BitmapFactory.Options mOptions;
WallpaperLoader() {
mOptions = new BitmapFactory.Options();
mOptions.inDither = false;
mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
protected Bitmap doInBackground(Integer... params) {
if (isCancelled()) return null;
try {
return BitmapFactory.decodeResource(getResources(),
mImages.get(params[0]), mOptions);
} catch (OutOfMemoryError e) {
return null;
}
}
protected void onPostExecute(Bitmap b) {
if (b == null) return;
if (!isCancelled() && !mOptions.mCancel) {
// Help the GC
if (mBitmap != null) {
mBitmap.recycle();
}
View v = getView();
if (v != null) {
mBitmap = b;
mWallpaperDrawable.setBitmap(b);
v.postInvalidate();
} else {
mBitmap = null;
mWallpaperDrawable.setBitmap(null);
}
mLoader = null;
} else {
b.recycle();
}
}
void cancel() {
mOptions.requestCancelDecode();
super.cancel(true);
}
}
/**
* Custom drawable that centers the bitmap fed to it.
*/
static class WallpaperDrawable extends Drawable {
Bitmap mBitmap;
int mIntrinsicWidth;
int mIntrinsicHeight;
/* package */void setBitmap(Bitmap bitmap) {
mBitmap = bitmap;
if (mBitmap == null)
return;
mIntrinsicWidth = mBitmap.getWidth();
mIntrinsicHeight = mBitmap.getHeight();
}
public void draw(Canvas canvas) {
if (mBitmap == null) return;
int width = canvas.getWidth();
int height = canvas.getHeight();
int x = (width - mIntrinsicWidth) / 2;
int y = (height - mIntrinsicHeight) / 2;
canvas.drawBitmap(mBitmap, x, y, null);
}
public int getOpacity() {
return android.graphics.PixelFormat.OPAQUE;
}
public void setAlpha(int alpha) {
// Ignore
}
public void setColorFilter(ColorFilter cf) {
// Ignore
}
}
}
Layouts
wallpaper_chooser.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/pinstripe_actionbar_tile_white"
android:orientation="vertical" >
<ImageView
android:id="#+id/wallpaper"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0"
android:scaleType="fitCenter" />
<Gallery
android:id="#+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/wallpaper_instructions"
android:textColor="#color/roboto" />
</LinearLayout>
wallpaper_item.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/wallpaper_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/gallery_item_background"
android:scaleType="fitXY"
android:focusable="true" />
I've should some of the following resources
GridView | Android Developers:http://developer.android.com/guide/topics/ui/layout/gridview.html
And a few others, I attempt to change everything over put end up bricking the entire code.
Any Help by Tips, Code, Example, Links, Support i'd extremely appreciate it all, Thank you.
I need to display infinite scroll of horizontal list view items(means need to repeat the items) for e.g
a,b,c,d,e,f,a,b,c,d,e,f,a,b,....
Bolded are Visible items on screen
The process is to repeat the list items after reaching the last list items, I tried to add list items on scrolling the list, so that I customized the horizontal list view class. But while scrolling to left after adding the list items on right, I get ArrayIndexOutOfBoundsException. I tried to add Integer.MAX VALUE option in base adapter to get infinite no of items but it has not helped while positioning the items(set selection()).
If anyone know how to add and remove horizontal list items means,please share it.
Instead of extending BaseAdapter extend ArrayAdapter.
Solution1::
Note::: Make the boolean variable isHorizontalListView = true in AgarwalActivity.java for horizontal listview.
HorizontalListView.java
public class HorizontalListView extends AdapterView<ListAdapter> {
public boolean mAlwaysOverrideTouch = true;
protected ListAdapter mAdapter;
private int mLeftViewIndex = -1;
private int mRightViewIndex = 0;
protected int mCurrentX;
protected int mNextX;
private int mMaxX = Integer.MAX_VALUE;
private int mDisplayOffset = 0;
protected Scroller mScroller;
private GestureDetector mGesture;
private Queue<View> mRemovedViewQueue = new LinkedList<View>();
private OnItemSelectedListener mOnItemSelected;
private OnItemClickListener mOnItemClicked;
private OnItemLongClickListener mOnItemLongClicked;
private boolean mDataChanged = false;
public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private synchronized void initView() {
mLeftViewIndex = -1;
mRightViewIndex = 0;
mDisplayOffset = 0;
mCurrentX = 0;
mNextX = 0;
mMaxX = Integer.MAX_VALUE;
mScroller = new Scroller(getContext());
mGesture = new GestureDetector(getContext(), mOnGesture);
}
#Override
public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
mOnItemSelected = listener;
}
#Override
public void setOnItemClickListener(AdapterView.OnItemClickListener listener){
mOnItemClicked = listener;
}
#Override
public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
mOnItemLongClicked = listener;
}
private DataSetObserver mDataObserver = new DataSetObserver() {
#Override
public void onChanged() {
synchronized(HorizontalListView.this){
mDataChanged = true;
}
invalidate();
requestLayout();
}
#Override
public void onInvalidated() {
reset();
invalidate();
requestLayout();
}
};
#Override
public ListAdapter getAdapter() {
return mAdapter;
}
#Override
public View getSelectedView() {
//TODO: implement
return null;
}
#Override
public void setAdapter(ListAdapter adapter) {
if(mAdapter != null) {
mAdapter.unregisterDataSetObserver(mDataObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mDataObserver);
reset();
}
private synchronized void reset(){
initView();
removeAllViewsInLayout();
requestLayout();
}
#Override
public void setSelection(int position) {
//TODO: implement
}
private void addAndMeasureChild(final View child, int viewPos) {
LayoutParams params = child.getLayoutParams();
if(params == null) {
params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
addViewInLayout(child, viewPos, params, true);
child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
}
#Override
protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if(mAdapter == null){
return;
}
if(mDataChanged){
int oldCurrentX = mCurrentX;
initView();
removeAllViewsInLayout();
mNextX = oldCurrentX;
mDataChanged = false;
}
if(mScroller.computeScrollOffset()){
int scrollx = mScroller.getCurrX();
mNextX = scrollx;
}
if(mNextX <= 0){
mNextX = 0;
mScroller.forceFinished(true);
}
if(mNextX >= mMaxX) {
mNextX = mMaxX;
mScroller.forceFinished(true);
}
int dx = mCurrentX - mNextX;
removeNonVisibleItems(dx);
fillList(dx);
positionItems(dx);
mCurrentX = mNextX;
if(!mScroller.isFinished()){
post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
requestLayout();
}
});
}
}
private void fillList(final int dx) {
int edge = 0;
View child = getChildAt(getChildCount()-1);
if(child != null) {
edge = child.getRight();
}
fillListRight(edge, dx);
edge = 0;
child = getChildAt(0);
if(child != null) {
edge = child.getLeft();
}
fillListLeft(edge, dx);
}
private void fillListRight(int rightEdge, final int dx) {
while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {
View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, -1);
rightEdge += child.getMeasuredWidth();
if(mRightViewIndex == mAdapter.getCount()-1) {
mMaxX = mCurrentX + rightEdge - getWidth();
}
if (mMaxX < 0) {
mMaxX = 0;
}
mRightViewIndex++;
}
}
private void fillListLeft(int leftEdge, final int dx) {
while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {
View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, 0);
leftEdge -= child.getMeasuredWidth();
mLeftViewIndex--;
mDisplayOffset -= child.getMeasuredWidth();
}
}
private void removeNonVisibleItems(final int dx) {
View child = getChildAt(0);
while(child != null && child.getRight() + dx <= 0) {
mDisplayOffset += child.getMeasuredWidth();
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mLeftViewIndex++;
child = getChildAt(0);
}
child = getChildAt(getChildCount()-1);
while(child != null && child.getLeft() + dx >= getWidth()) {
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mRightViewIndex--;
child = getChildAt(getChildCount()-1);
}
}
private void positionItems(final int dx) {
if(getChildCount() > 0){
mDisplayOffset += dx;
int left = mDisplayOffset;
for(int i=0;i<getChildCount();i++){
View child = getChildAt(i);
int childWidth = child.getMeasuredWidth();
child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
left += childWidth;
}
}
}
public synchronized void scrollTo(int x) {
mScroller.startScroll(mNextX, 0, x - mNextX, 0);
requestLayout();
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handled = super.dispatchTouchEvent(ev);
handled |= mGesture.onTouchEvent(ev);
return handled;
}
protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
synchronized(HorizontalListView.this){
mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);
}
requestLayout();
return true;
}
protected boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
return true;
}
private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
return HorizontalListView.this.onDown(e);
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
synchronized(HorizontalListView.this){
mNextX += (int)distanceX;
}
requestLayout();
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
for(int i=0;i<getChildCount();i++){
View child = getChildAt(i);
if (isEventWithinView(e, child)) {
if(mOnItemClicked != null){
mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
}
if(mOnItemSelected != null){
mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
}
break;
}
}
return true;
}
#Override
public void onLongPress(MotionEvent e) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (isEventWithinView(e, child)) {
if (mOnItemLongClicked != null) {
mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
}
break;
}
}
}
private boolean isEventWithinView(MotionEvent e, View child) {
Rect viewRect = new Rect();
int[] childPosition = new int[2];
child.getLocationOnScreen(childPosition);
int left = childPosition[0];
int right = left + child.getWidth();
int top = childPosition[1];
int bottom = top + child.getHeight();
viewRect.set(left, top, right, bottom);
return viewRect.contains((int) e.getRawX(), (int) e.getRawY());
}
};
}
AgarwalActivity.java
public class AgarwalActivity extends Activity{
private LayoutInflater _inflater;
private ListView listView;
private HorizontalListView hListView;
private RankingsAdapter rankingsAdapter;
private boolean isHorizontalListView = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(isHorizontalListView){
setContentView(R.layout.listviewdemo);
hListView = (HorizontalListView) findViewById(R.id.listview);
}else{
setContentView(R.layout.listview);
listView=(ListView)findViewById(R.id.listView);
}
ArrayList<String> rankingArrayList = new ArrayList<String>();
for(int i=0;i<25;i++)
rankingArrayList.add("agarwal"+i);
_inflater= LayoutInflater.from(AgarwalActivity.this);
rankingsAdapter = new RankingsAdapter(AgarwalActivity.this,R.id.text,rankingArrayList);
if(isHorizontalListView)
hListView.setAdapter(rankingsAdapter);
else
listView.setAdapter(rankingsAdapter);
}
private class RankingsAdapter extends ArrayAdapter<String>{
private ArrayList<String> _row_list;
public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
public final int MIDDLE;
public RankingsAdapter(Context context,int textViewResourceId,ArrayList<String> arrL) {
// TODO Auto-generated constructor stub
super(context,textViewResourceId, arrL);
_row_list = arrL;
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % _row_list.size();
}
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}
public String getItem(int position) {
// TODO Auto-generated method stub
return _row_list.get(position % _row_list.size());
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position % _row_list.size();
}
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder = null;
if(convertView == null){
holder = new ViewHolder();
convertView = (LinearLayout)_inflater.inflate(R.layout.text_layout, null);
//getting the IDs
holder.driver = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder=(ViewHolder)convertView.getTag();
}
//Settng bean values to row components
holder.driver.setText(_row_list.get(position % _row_list.size()));
return convertView;
}//getView()
class ViewHolder{
//holding the components
TextView driver;
}//ViewHolder--Class inside CountriesAdapter
}//RankingsAdapter-inner class
}//AgarwalActivity-class
listview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</RelativeLayout>
listviewdemo.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#fff"
>
<com.vl.agarwal.HorizontalListView
android:id="#+id/listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ddd"
/>
</LinearLayout>
text_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="6dip"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
-------------------------------------------------------------------------------------
Solution2:: Using the gallery as horizontal listview
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/itemtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:textColor="#android:color/white"
android:textStyle="bold"
android:textSize="30sp"/>
</LinearLayout>
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<Gallery
android:id="#+id/horizontallistview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
AgarwalActivity.java
public class AgarwalActivity extends Activity {
Gallery myHorizontalListView;
private RankingsAdapter rankingsAdapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<String> rankingArrayList = new ArrayList<String>();
for(int i=0;i<25;i++)
rankingArrayList.add("agarwal"+i);
DisplayMetrics metrics = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(metrics);
myHorizontalListView = (Gallery)findViewById(R.id.horizontallistview);
MarginLayoutParams mlp = (MarginLayoutParams) myHorizontalListView.getLayoutParams();
mlp.setMargins(-(metrics.widthPixels/2),
mlp.topMargin,
mlp.rightMargin,
mlp.bottomMargin
);
rankingsAdapter = new RankingsAdapter(AgarwalActivity.this,R.id.itemtext,rankingArrayList);
myHorizontalListView.setAdapter(rankingsAdapter);
myHorizontalListView.setSelection(10,true);
myHorizontalListView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast.makeText(
AgarwalActivity.this,
parent.getItemAtPosition(position).toString() + " Clicked",
Toast.LENGTH_LONG)
.show();
}});
}
private class RankingsAdapter extends ArrayAdapter<String>{
private ArrayList<String> _row_list;
public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
public final int MIDDLE;
public RankingsAdapter(Context context,int textViewResourceId,ArrayList<String> arrL) {
// TODO Auto-generated constructor stub
super(context,textViewResourceId, arrL);
_row_list = arrL;
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % _row_list.size();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}
#Override
public String getItem(int position) {
// TODO Auto-generated method stub
return _row_list.get(position % _row_list.size());
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position % _row_list.size();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View rowView = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.row, null);
TextView listTextView = (TextView)rowView.findViewById(R.id.itemtext);
listTextView.setText(_row_list.get(position % _row_list.size()));
return rowView;
}//getView()
}//RankingsAdapter-inner class
}//AgarwalActivity-class
What you are describing is sometimes called a circular gallery, a wrapping gallery, or a turnstyle gallery. There are good code examples on this posting:
android circular gallery?