首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >线性布局的字幕效果

线性布局的字幕效果
EN

Stack Overflow用户
提问于 2015-07-17 16:36:11
回答 2查看 4.1K关注 0票数 17

我正在尝试实现字幕效果的布局,以帮助它滚动/动画从右内侧到左内侧,就像滚动条视图。

通过以下两个链接,您将能够获得更多知识,就像股票市场通过以循环常数的方式显示值来保持用户更新一样。

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>

通过实现这一点,我在某种程度上接近了目标,但无法实现所需的目标。请帮助我使它循环,没有任何中断,并重新开始滚动后,最后的数据从左侧移动到里面。

以下是所需的结果:

我还检查了this link,它提供了所需的滚动效果,但没有显示整个数据,它只显示了3到4个视图,但正如你所看到的,我在适配器类中添加了10个数据。

任何形式的帮助都是值得欣赏的。

提前谢谢。

EN

回答 2

Stack Overflow用户

发布于 2015-07-29 17:54:13

它可以使用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);
 }
}

SampleAdapter(ScrollAdapter.java) 2.

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>

增加或减少pixelsToMove,此变量值可更改速度

票数 12
EN

Stack Overflow用户

发布于 2015-07-24 13:03:27

你可以使用一个叫做MarqueeView的库来解决这个问题,这个库我已经使用了一段时间了,它工作得很好。Here是它的链接。

用法

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();
            }
        });

请查看此sample项目以获取更多帮助。

我建议您在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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31471552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档