线性布局的选取框效果

我正在尝试对布局实现选取框效果,以便像滚动视图一样从右侧内侧滚动到左侧内侧。

从以下两个环节中,您将能够获得更多的知识,就像股票市场以循环不断的方式显示价值来更新用户一样。

1) http://www.sify.com/finance/livemarkets/

2) http://terminal.moneycontrol.com/index.php?wl=indices

对于这个我已经实现了下面的代码,使有点类似。

public class HorizonalSlideActivity extends Activity { private LinearLayout horizontalOuterLayout; private HorizontalScrollView horizontalScrollview; private int scrollMax; private int scrollPos = 0; private TimerTask scrollerSchedule; private Timer scrollTimer = null; private ScrollAdapter adapter = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.horizontal_layout); adapter = new ScrollAdapter(HorizonalSlideActivity.this); horizontalScrollview = (HorizontalScrollView) findViewById(R.id.horiztonal_scrollview_id); horizontalScrollview.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } }); horizontalOuterLayout = (LinearLayout) findViewById(R.id.horiztonal_outer_layout_id); horizontalTextView = (TextView) findViewById(R.id.horizontal_textview_id); horizontalScrollview.setHorizontalScrollBarEnabled(false); addData(); ViewTreeObserver vto = horizontalOuterLayout.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { horizontalOuterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); getScrollMaxAmount(); startAutoScrolling(); } }); } private void addData() { for (int i = 0; i < adapter.getCount(); i++) { View convertView = adapter.getView(i, null, null); horizontalOuterLayout.addView(convertView); } } public void getScrollMaxAmount() { Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; Log.e("getScrollMaxAmount", "getWidth == "+width); Log.e("getScrollMaxAmount", "getMeasuredWidth == "+horizontalOuterLayout.getMeasuredWidth()); int actualWidth = (horizontalOuterLayout.getMeasuredWidth() - width); Log.e("getScrollMaxAmount", "actualWidth == "+actualWidth); scrollMax = actualWidth; Log.e("getScrollMaxAmount", "scrollMax == "+scrollMax); } public void startAutoScrolling() { if (scrollTimer == null) { scrollTimer = new Timer(); final Runnable TimerTick = new Runnable() { public void run() { moveScrollView(); } }; if (scrollerSchedule != null) { scrollerSchedule.cancel(); scrollerSchedule = null; } scrollerSchedule = new TimerTask() { @Override public void run() { runOnUiThread(TimerTick); } }; scrollTimer.schedule(scrollerSchedule, 3000, 30); } } public void moveScrollView() { Log.e("moveScrollView", "scrollMax == "+scrollMax); scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0); Log.e("moveScrollView", "scrollPos == "+scrollPos); if (scrollPos >= scrollMax) { scrollPos = 0; } horizontalScrollview.scrollTo(scrollPos, 0); } public void stopAutoScrolling() { if (scrollTimer != null) { scrollTimer.cancel(); scrollTimer = null; } } public void onBackPressed() { super.onBackPressed(); finish(); } public void onPause() { super.onPause(); finish(); } public void onDestroy() { clearTimerTaks(scrollerSchedule); clearTimers(scrollTimer); scrollerSchedule = null; scrollTimer = null; super.onDestroy(); } private void clearTimers(Timer timer) { if (timer != null) { timer.cancel(); timer = null; } } private void clearTimerTaks(TimerTask timerTask) { if (timerTask != null) { timerTask.cancel(); timerTask = null; } } } 

这是这个文件的布局:

 <?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" > <HorizontalScrollView android:id="@+id/horiztonal_scrollview_id" android:layout_width="match_parent" android:layout_height="wrap_content" android:fadingEdge="none" > <LinearLayout android:id="@+id/horiztonal_outer_layout_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ffffff" android:gravity="center_vertical" android:orientation="horizontal" android:paddingBottom="5dip" android:paddingTop="5dip" > </LinearLayout> </HorizontalScrollView> </LinearLayout> 

适配器类显示数据:

 public class ScrollAdapter extends BaseAdapter { private Context context; public ScrollAdapter(Context context) { this.context = context; } @Override public int getCount() { return 10; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = ((Activity)context).getLayoutInflater(); convertView = inflater.inflate(R.layout.scroll_child, null); return convertView; } } 

和它的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/txtPercent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="0.14%" /> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/white" /> <TextView android:id="@+id/txtData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="data" /> </LinearLayout> 

通过实施这一点,我有点接近,但无法达到目标。 请帮助我在不中断的情况下循环,并在最后一个数据从左侧移动到内部后重新开始滚动。

这是所需的结果:

在这里输入图像说明

我也检查了这个链接 ,它提供了滚动效果,但不显示整个数据,它只显示3到4个视图,但你可以看到我已经在适配器类中添加了10个数据。

任何forms的帮助将是可观的。

提前致谢。

Solutions Collecting From Web of "线性布局的选取框效果"

它可以使用Recycleview和自动滚动可运行来完成。 在这里添加代码片段

1. MainActivity(MarqueeViewSample.java)

 package com.test.mo.test; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; /** * Created by jovin.pj on 29-07-2015. */ public class MarqueeViewSample extends Activity { private final Runnable SCROLLING_RUNNABLE = new Runnable() { @Override public void run() { final int duration = 10; final int pixelsToMove = 10; marqueList.smoothScrollBy(pixelsToMove, 0); mHandler.postDelayed(this, duration); } }; private final Handler mHandler = new Handler(Looper.getMainLooper()); private RecyclerView marqueList; //private boolean loading = true; private boolean foundTotalPixel = true; private int pastVisiblesItems, visibleItemCount, totalItemCount; private int totalMovedPixel; private int totalPixel; /** * Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); marqueList = (RecyclerView) findViewById(R.id.marqueList); final LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); marqueList.setLayoutManager(layoutManager); marqueList.setAdapter(new ScrollAdapter()); marqueList.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { totalMovedPixel = totalMovedPixel + dx; visibleItemCount = layoutManager.getChildCount(); totalItemCount = layoutManager.getItemCount(); pastVisiblesItems = layoutManager.findFirstVisibleItemPosition(); if (foundTotalPixel) { if (totalItemCount > 2) { View headerView = layoutManager.getChildAt(0); View itemView = layoutManager.getChildAt(1); if (itemView != null && headerView != null) { /*total visible scrolling part is total pixel's of total item's count and header view*/ totalPixel = /*-c.getTop() +*/ ((totalItemCount - 2) * itemView.getWidth()) + (1 * headerView.getWidth()); Log.v("...", "Total pixel x!" + totalPixel); foundTotalPixel = false; } } } //if (loading) { //if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) { if (!foundTotalPixel && totalMovedPixel >= totalPixel) { // loading = false; Log.v("...", "Last Item Wow !"); Log.v("...", "totalMovedPixel !" + totalMovedPixel); // use this to turn auto-scrolling off: //mHandler.removeCallbacks(SCROLLING_RUNNABLE); marqueList.setAdapter(null); marqueList.setAdapter(new ScrollAdapter()); pastVisiblesItems = visibleItemCount = totalItemCount = 0; totalMovedPixel = 0; } } // } }); // use this to turn auto-scrolling on: mHandler.post(SCROLLING_RUNNABLE); } } 

2. SampleAdapter(ScrollAdapter.java)

 package com.test.mo.test; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; /** * Created by jovin.pj on 29-07-2015. */ public class ScrollAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_HEADER = 0; private static final int TYPE_ITEM = 1; private static final int TYPE_FOOTER = 2; @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder viewHolder = null; if (viewType == TYPE_ITEM) { //inflate your layout and pass it to view holder View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.scroll_child, parent, false); viewHolder = new ViewHolderItem(view); } else if (viewType == TYPE_HEADER || viewType == TYPE_FOOTER) { //inflate your layout and pass it to view holder //View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_footer, parent, false); View view = new View(parent.getContext()); DisplayMetrics metrics = parent.getContext().getResources().getDisplayMetrics(); int width = metrics.widthPixels; view.setLayoutParams(new LinearLayout.LayoutParams(width, LinearLayout.LayoutParams.WRAP_CONTENT)); viewHolder = new ViewHolderHeaderOrFooter(view); } return viewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } @Override public int getItemCount() { // 1 for header and 1 for footer return 4 + 1 + 1; } @Override public int getItemViewType(int position) { if (isPositionHeader(position)) return TYPE_HEADER; else if (isPositionFooter(position)) return TYPE_FOOTER; return TYPE_ITEM; } private boolean isPositionHeader(int position) { return position == 0; } private boolean isPositionFooter(int position) { return position == getItemCount() - 1; } // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolderItem extends RecyclerView.ViewHolder { // each data item is just a string in this case public View mView; public ViewHolderItem(View v) { super(v); mView = v; } } // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolderHeaderOrFooter extends RecyclerView.ViewHolder { // each data item is just a string in this case public View mView; public ViewHolderHeaderOrFooter(View v) { super(v); mView = v; } } } 

3.主要活动的布局文件(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"> <android.support.v7.widget.RecyclerView android:id="@+id/marqueList" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:clipToPadding="false" /> </LinearLayout> 

4.适配器的布局文件(scroll_child.xml)

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/txtPercent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="0.14%" /> <View android:layout_width="match_parent" android:layout_height="1px" android:background="@android:color/darker_gray" /> <TextView android:id="@+id/txtData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="30dp" android:paddingRight="30dp" android:text="data" /> </LinearLayout> 

增加或减lesspixelsToMove ,这个variables值改变速度

你可以使用库, MarqueeView来解决这个问题 ,我已经使用了一段时间,它的作品很棒。 这是它的链接。

用法

XML中

 <asia.ivity.android.marqueeview.MarqueeView android:id="@+id/marqueeView150" android:layout_width="150dp" android:layout_height="wrap_content" marquee:speed="5" marquee:pause="1000" marquee:autoStart="true" > <TextView android:id="@+id/textView2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do." android:textSize="20sp" android:textStyle="bold" android:singleLine="true" android:ellipsize="end" tools:ignore="HardcodedText"/> </asia.ivity.android.marqueeview.MarqueeView> 

Java中

 final MarqueeView mv = (MarqueeView) findViewById(R.id.marqueeView100); mv.setPauseBetweenAnimations(500); mv.setSpeed(10); getWindow().getDecorView().post(new Runnable() { @Override public void run() { mv.startMarquee(); } }); 

请检查此示例项目以获取更多帮助。

我build议你在MarqueeView使用一个单独的TextView ,并将“百分比”和“数据”结合起来。

您可以绝对使用Spannable自定义TextView各部分的文本大小,字体样式,颜色等属性。

这里给你一个小例子,

 Spannable spn = (Spannable) tv3.getText(); spn.setSpan(new BackgroundColorSpan(Color.RED), 0, 7,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spn.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC),0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 

你可以很明显地按照你想给百分比和数据在单个TextView中看到的方式来定制它。

您还可以在任何需要使用ImageSpan地方在TextView中显示图像,

这是一个简单的例子,

 ImageSpan is = new ImageSpan(context, resId); text.setSpan(is, index, index + strLength, 0); 

只要确保你使用了正确的索引位置,否则最终会出现StringIndexOutOfBoundsException