android一些问题解决

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">
</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">1.启动APP时闪退,日志错误显示为 </span>

<span style="font-size:14px;">java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setOnClickListener(android.view.View$OnClickListener)' on a null object reference</span>
最终在StackOverFlow中找到原因及解决办法,原因是我在主Activity中设置点击事件的这个ImageButton是在我的ListView的单独的Item布局文件中,即ListView和Item是两个Layout的xml,而主Activity中  setContentView(R.layout.activity_phone_list);  是设置ListView所在的布局文件为Activity的显示界面,所以其实主Activity是获取不到Item布局文件中定义的那个ImageButton的引用的,自然当设置监听事件时会报null object reference。

下图为StackOverFlow 中的回答,箭头部分表示要从接收该布局文件的Activity中获得该组件。


还有另一位博主的一篇文章讲为ListView每个Item上面的按钮添加事件,地址为 为ListView每个Item上面的按钮添加事件,其中的第二种方法值得借鉴。




2.ListView的Item无法响应点击事件(不能获得焦点can't take focus),因为我在Item布局文件中加入了一个ImageButton,而它默认会主动获得焦点


 “ 通常,我们会自定义 ListView Item 的 Layout,当自定义的 Item Layout 含有主动获得焦点的控件时(例如 Button, ImageButton 等),那么我们就没办法点击 ListView Item 自己的点击事件。

解决办法很简单,只要在Item Layout 的根布局中加上 android:descendantFocusability = "blocksDescendants"属性即可。如下方的 Item 布局文件所示:

Java

这里再说说 descendantFocusability 这个属性的作用。

根据 官方说明 ,descendantFocusability 定义了 ViewGroup 和子控件的在获取焦点时的关系。

有下面三种取值:

  • beforeDescendants,ViewGroup 会在所有子控件之前获得焦点
  • afterDescendants,ViewGroup 会在所有子控件都不需要焦点时获得焦点
  • blocksDescendants,ViewGroup会阻断子控件获得焦点。

通常,我们只要把 descendantFocusability 设置为 blocksDescendants,即可解决由于 Item 里的 Button 抢夺焦点导致 Item 本身无法点击的问题。”

以上是网搜到的Item抢占焦点的办法,,然而这样我Item中的ImageButton也不能点击了,我想的是每个item一个点击事件,Item中的ImageButton(Button也适用)有自己单独的点击事件,实现不同的功能,而不是只能点击整个Item一个事件,还没解决,未完待续……

接上面的问题,我看到别人关于item和item中点击事件都生效的一篇文章在Activity中响应ListView内部按钮的点击事件其中介绍了使用接口回调使用抽象类回调两种方法,我试了一下抽象类回调然后加上之前的descendantFocusability 设置为 blocksDescendants,成功解决了Item和Item中控件不同的点击响应。


3.如何变相地改变启动页以避免用户每次启动APP时都要登录,有一种解决办法是将用户名密码保存在SharedPreferences里面,然后将加载界面设置为启动页,在加载的时候验证SharedPreferences中用户名密码是否存在并且正确,如果正确则在加载后启动登录后的界面,不是则加载后进入登录界面。


4.loading(加载)页中用线程做一个ImageView的Alpha渐变动画效果然后设置一段时间延迟启动其他界面,如

 launch.postDelayed(new Runlaunch(),2500);//设置2.5秒钟延迟执行Runlaunch线程,launch是新建的Handler对象
我直接贴自己的代码吧

    private ImageView ivstart1,ivstart2;
    static int image_alpha1=255;//第一段动画Alpha值
    static int image_alpha2=0;//第二段动画Alpha值
    Handler launch;
    boolean isrun1=true;//线程是否执行第一段动画
    boolean isrun2=false;//线程是否执行第二段动画
    private int runtime=0;//用以判断该轮到哪段动画了,变量递增,递增到100时换第二段动画
    static boolean isLogin=false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);
        init();

        ivstart2.setAlpha(image_alpha2);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(isrun1){
                    try {
                        Thread.sleep(70);//每次线程睡眠时间70ms
                        updateAlpha();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                while(isrun2){
                    try {
                        Thread.sleep(100);
                        updateAlpha();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        //接收消息之后更新imageview视图

        launch=new Handler(){
            public void handleMessage(Message msg){
                super.handleMessage(msg);
                ivstart1.setAlpha(image_alpha1);
                ivstart2.setAlpha(image_alpha2);
                ivstart1.invalidate();//刷新视图
                ivstart2.invalidate();
            }
        };
        launch.postDelayed(new Runlaunch(),2500);//设置2.5秒钟延迟执行Runlaunch线程

    }

    private void updateAlpha() {
        while(runtime<100){

            if (image_alpha1 > 120) {

                image_alpha1-=14;
            }else{
                image_alpha1=0;
                isrun1=false;
                image_alpha2=100;
            }
            runtime+=10;
            break;
        }
        while(runtime>=100){
            isrun2=true;
            if(image_alpha2<200){
                image_alpha2+=10;
            }else{
                image_alpha2=255;
                isrun2=false;
            }
            runtime+=10;
            break;
        }
        launch.sendMessage(launch.obtainMessage()); // 发送需要更新imageview视图的消息-->这里是发给主线程
    }

    class Runlaunch implements Runnable{

        @Override
        public void run() {
            startActivity(new Intent(LaunchActivity.this,LoginActivity.class));
            LaunchActivity.this.finish();
        }
    }
我这里 是设置了两段渐变动画,就用自己定义的一个runtime变量区分,runtime为0~100时第一段Alpha动画,递增到100时换成第二段Alpha动画。过程是这样的,线程每次先判断布尔值isrun是否为真,是则执行改变Alpha的方法updateAlpha(),方法中每次改变Alpha值时,都要发送需要更新ImageView视图的消息给Handler对象launch,然后launch设置Alpha值并且刷新视图,这样通过每次短时间间隔的刷新ImageView的Alpha值看上去就好像是一个持续的渐变动画了。

5.Android获取系统当前时间

一:

import    java.text.SimpleDateFormat;       
       
SimpleDateFormat    formatter    =   new    SimpleDateFormat    ("yyyy年MM月dd日    HH:mm:ss     ");  //这部分格式可以自己改,比如<pre name="code" class="java" style="font-size: 14px; line-height: 25.2px;">"yyyy-MM-dd    HH时mm分" 这样,在其中插入换行符这些也可以
Date curDate = new Date(System.currentTimeMillis());//获取当前时间 String str = formatter.format(curDate);

 
二:用android中的Time类 

import android.text.format.Time;
           
Time t=new Time();
            t.setToNow();//取得系统时间
            String year=t.year+"年"+t.month+"月"+t.monthDay+"日"+"  "+t.hour+":"+t.minute+":"+t.second;

如何获取系统时间是12小时制还是24小时制?

ContentResolver cv = getContentResolver();  
       String strTimeFormat =android.provider.Settings.System.getString(cv,  
                                          android.provider.Settings.System.TIME_12_24); //android是小写!  
        
       if(strTimeFormat.equals("24"))  
      {  
              Log.i("timeformat","24");  
       }else Log.i("timeformat","12"); 


6.报错

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare();
原因及解决办法:

Android basically works on two thread types namely UI thread and background thread. According to android documentation -

Do not access the Android UI toolkit from outside the UI thread to fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

Activity.runOnUiThread(Runnable)  
View.post(Runnable)  
View.postDelayed(Runnable, long)

Now there are various methods to solve this problem. I will explain it by code sample

runOnUiThread

new Thread()
{
    public void run()
    {
        myactivity.this.runOnUiThread(new runnable()
        {
            public void run()
            {
                //Do your UI operations like dialog opening or Toast here
            }
        });
    }
}.start();

LOOPER

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();
    }

AsyncTask

AsyncTask allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.

public void onClick(View v) {
    new CustomTask().execute((Void[])null);
}


private class CustomTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... param) {
        //Do some work
        return null;
    }

    protected void onPostExecute(Void param) {
        //Print Toast or open dialog
    }
}

Handler

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.

Message msg = new Message();


    new Thread()
    {
        public void run()
        {
            msg.arg1=1;
            handler.sendMessage(msg);
        }
    }.start();



    Handler handler = new Handler(new Handler.Callback() {

        @Override
        public boolean handleMessage(Message msg) {
            if(msg.arg1==1)
            {
                //Print Toast or open dialog        
            }
            return false;
        }
    });

7.报错

android.content.res.Resources android.content.Context.getResources()' on a null object reference
解决办法:为在出错的地方为context处加上上下文,可以是onCreate方法里面构造的时候添加MainActivity.this等Context内容

 Bitmap bitmap=downloadImage();
            BitmapDrawable bd=new BitmapDrawable(context.getResources(),bitmap);//Create drawable from a bitmap, setting initial target density based on

8.LinearLayout分开布局

我们知道LinearLayout是按照指定的朝向(orientation)顺序地摆放组件的,所以有一种推荐的分开布局方法是在其中加入一个看不见的View,如水平布局中想要左右分开布局,使控件分别在左右两端可以这样

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orietation="horizontal">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="start"
                android:text="zzz"/>
            <!--加入“隐形”View达到LinearLayout左右布局的目的-->
            <View
                android:layout_width="0dp"
                android:layout_weight="1.0"
                android:layout_height="0dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="right"
                android:text="yyy" />
        </LinearLayout>

看不见的View填充了中间的空白部分。









  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值